blob: bc971a619c8c3b0fe631e4045981a2c2ee63b063 [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
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700139}
140
Mahir Gunyela2e68702022-12-07 00:00:42 -0800141// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700142type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400143 deviceID string
144 deviceType string
145 serialNumber string
Akash Kankanala041a2122024-10-16 15:49:22 +0530146 proxyDeviceID string
147 adapterEndpoint string
khenaidoo106c61a2021-08-11 18:05:46 -0400148 onuID uint32
149 intfID uint32
khenaidoo106c61a2021-08-11 18:05:46 -0400150 losRaised bool
151 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700152}
153
Mahir Gunyelb0046752021-02-26 13:51:05 -0800154type onuIndicationMsg struct {
155 ctx context.Context
156 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800157}
158
159type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800160 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800161 stopChannel chan struct{}
162}
163
Mahir Gunyela2e68702022-12-07 00:00:42 -0800164// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
165// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
166// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
167// 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 -0800168type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400169 ctx context.Context // Flow/group handler context
khenaidoodc2116e2021-10-19 17:33:19 -0400170 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
171 group *of.OfpGroupEntry // Group message (can be nil or valid group)
172 errChan *chan error // channel to report the mcast Flow/group handling error
Akash Kankanala041a2122024-10-16 15:49:22 +0530173 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
Girish Gowdra491a9c62021-01-06 16:43:07 -0800174}
175
Naga Manjunath7615e552019-10-11 22:35:47 +0530176var pmNames = []string{
177 "rx_bytes",
178 "rx_packets",
179 "rx_mcast_packets",
180 "rx_bcast_packets",
181 "tx_bytes",
182 "tx_packets",
183 "tx_mcast_packets",
184 "tx_bcast_packets",
185}
186
Mahir Gunyela2e68702022-12-07 00:00:42 -0800187// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400188func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700189 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700190 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700191 device.deviceType = deviceTp
192 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700193 device.onuID = onuID
194 device.intfID = intfID
195 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530196 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400197 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700198 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530199}
200
Mahir Gunyela2e68702022-12-07 00:00:42 -0800201// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400202func 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 -0700203 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530204 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800205 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400206 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400207 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700208 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700209 dh.device = cloned
210 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500211 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700212 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000213 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
214 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530215 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 -0500216 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800217 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800218 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400219 dh.childAdapterClients = make(map[string]*vgrpc.Client)
220 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300221 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530222 if dh.kvStore == nil {
223 logger.Error(ctx, "Failed to setup KV store")
224 return nil
225 }
226
Girish Gowdra491a9c62021-01-06 16:43:07 -0800227 // Create a slice of buffered channels for handling concurrent mcast flow/group.
228 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700229 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
230 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800231 for i := range dh.incomingMcastFlowOrGroup {
232 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800233 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800234 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
235 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
236 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
237 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700238 dh.mcastHandlerRoutineActive[i] = true
239 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800240 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530241 // TODO initialize the support classes.
cuilin20187b2a8c32019-03-26 19:52:28 -0700242 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530243}
244
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530245func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
246 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
247 switch storeType {
248 case "etcd":
249 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Abhay Kumar9bcfeb22024-07-12 09:14:25 +0530250 case "redis":
251 return kvstore.NewRedisClient(address, timeout, false)
252 case "redis-sentinel":
253 return kvstore.NewRedisClient(address, timeout, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530254 }
255 return nil, errors.New("unsupported-kv-store")
256}
257
258// SetKVClient sets the KV client and return a kv backend
259func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
260 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
261 if err != nil {
262 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
263 return nil
264 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530265 kvbackend := &db.Backend{
266 Client: kvClient,
267 StoreType: backend,
268 Address: addr,
269 Timeout: rsrcMgr.KvstoreTimeout,
270 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
271
272 return kvbackend
273}
274
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000275// CloseKVClient closes open KV clients
276func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
277 if dh.resourceMgr != nil {
278 for _, rscMgr := range dh.resourceMgr {
279 if rscMgr != nil {
280 rscMgr.CloseKVClient(ctx)
281 }
282 }
283 }
284 if dh.flowMgr != nil {
285 for _, flMgr := range dh.flowMgr {
286 if flMgr != nil {
287 flMgr.CloseKVClient(ctx)
288 }
289 }
290 }
291}
292
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530293// start save the device to the data model
294func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700295 dh.lockDevice.Lock()
296 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000297 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700298 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000299 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530300}
301
khenaidooefff76e2021-12-15 16:51:30 -0500302// Stop stops the device handler
303func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700304 dh.lockDevice.Lock()
305 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000306 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500307 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400308
khenaidooefff76e2021-12-15 16:51:30 -0500309 // Delete (which will stop also) all grpc connections to the child adapters
310 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000311 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530312}
313
ssiddiqui04386ee2021-08-23 21:58:25 +0530314func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
315 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
316 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
317 if pooledIntfID == intfID {
318 return resourceRanges.GetTechnology()
319 }
320 }
321 }
322 return ""
323}
324
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400325func macifyIP(ip net.IP) string {
326 if len(ip) > 0 {
327 oct1 := strconv.FormatInt(int64(ip[12]), 16)
328 oct2 := strconv.FormatInt(int64(ip[13]), 16)
329 oct3 := strconv.FormatInt(int64(ip[14]), 16)
330 oct4 := strconv.FormatInt(int64(ip[15]), 16)
331 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
332 }
333 return ""
334}
335
Neha Sharma96b7bf22020-06-15 10:37:32 +0000336func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400337 var genmac string
338 var addr net.IP
339 var ips []string
340 var err error
341
Neha Sharma96b7bf22020-06-15 10:37:32 +0000342 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400343
344 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000345 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400346
347 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000348 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400349 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000350 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400351 }
352 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000353 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530354 log.Fields{"host": ips[0],
355 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400356 return genmac, nil
357 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000358 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400359 }
360
361 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000362 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530363 log.Fields{"host": host,
364 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400365 return genmac, nil
366}
367
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530368func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700369 slist := strings.Split(mac, ":")
370 result := make([]uint32, len(slist))
371 var err error
372 var tmp int64
373 for index, val := range slist {
374 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
375 return []uint32{1, 2, 3, 4, 5, 6}
376 }
377 result[index] = uint32(tmp)
378 }
379 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530380}
381
Mahir Gunyela2e68702022-12-07 00:00:42 -0800382// 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 -0800383func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800384 switch portType {
385 case voltha.Port_ETHERNET_NNI:
386 return fmt.Sprintf("nni-%d", portNum), nil
387 case voltha.Port_PON_OLT:
388 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700389 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800390
Girish Kumarf26e4882020-03-05 06:49:10 +0000391 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530392}
393
Elia Battiston596406d2022-02-02 12:19:00 +0100394func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
395 if speedMbps == 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530396 // In case it was not set in the indication
397 // and no other value was provided
Elia Battiston596406d2022-02-02 12:19:00 +0100398 speedMbps = defaultPortSpeedMbps
399 }
400
401 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
402 switch speedMbps {
403 case 1000000:
404 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
405 case 100000:
406 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
407 case 40000:
408 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
409 case 10000:
410 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
411 case 1000:
412 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
413 case 100:
414 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
415 case 10:
416 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
417 }
418
419 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
420
421 port := &of.OfpPort{
422 HwAddr: macAddressToUint32Array(macAddress),
423 Config: 0,
424 State: uint32(of.OfpPortState_OFPPS_LIVE),
425 Curr: capacity,
426 Advertised: capacity,
427 Peer: capacity,
Akash Kankanala041a2122024-10-16 15:49:22 +0530428 CurrSpeed: speedMbps * 1000, // kbps
429 MaxSpeed: speedMbps * 1000, // kbps
Elia Battiston596406d2022-02-02 12:19:00 +0100430 }
431
432 return port
433}
434
435func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000436 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700437 if state == "up" {
438 operStatus = voltha.OperStatus_ACTIVE
Akash Kankanala041a2122024-10-16 15:49:22 +0530439 // populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500440 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700441 } else {
442 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500443 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700444 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700445 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400446 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800447 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000448 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400449 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500450
khenaidoo106c61a2021-08-11 18:05:46 -0400451 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400452 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400453 DeviceId: dh.device.Id,
454 Port: portNum,
455 })
456 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000457 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400458 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400459 DeviceId: dh.device.Id,
460 PortType: portType,
461 PortNo: portNum,
462 OperStatus: operStatus})
463 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400464 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
465 "device-id": dh.device.Id,
466 "port-type": portType,
467 "port-number": portNum,
468 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500469 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400470 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500471 }
khenaidoo106c61a2021-08-11 18:05:46 -0400472
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400473 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400474 port = &voltha.Port{
475 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700476 PortNo: portNum,
477 Label: label,
478 Type: portType,
479 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100480 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700481 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000482 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700483 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400484 err = dh.createPortInCore(ctx, port)
485 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000486 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000488 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400489 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000490 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530491 return nil
492}
493
Kent Hagermane6ff1012020-07-14 15:07:53 -0400494func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400495 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530496 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400497 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
498 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530499 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800500 dh.lockDevice.Lock()
501 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530502 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530503}
504
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700505// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530506// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800507func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000508 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700509 defer func() {
510 dh.lockDevice.Lock()
511 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530512 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700513 dh.lockDevice.Unlock()
514 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700515 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700516 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700517 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700518 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400519
David Bainbridgef5879ca2019-12-13 21:17:54 +0000520 // Create an exponential backoff around re-enabling indications. The
521 // maximum elapsed time for the back off is set to 0 so that we will
522 // continue to retry. The max interval defaults to 1m, but is set
523 // here for code clarity
524 indicationBackoff := backoff.NewExponentialBackOff()
525 indicationBackoff.MaxElapsedTime = 0
526 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700527
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700528 dh.lockDevice.Lock()
529 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530530 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700531 dh.lockDevice.Unlock()
532
Girish Gowdra3f974912020-03-23 20:35:18 -0700533Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700534 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400535 select {
536 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000537 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700538 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400539 default:
540 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100541
542 select {
543 case <-indications.Context().Done():
544 if err != nil {
545 logger.Warnw(ctx, "error-during-enable-indications",
546 log.Fields{"err": err,
547 "device-id": dh.device.Id})
548 }
549
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400550 // Use an exponential back off to prevent getting into a tight loop
551 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100552 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
553 "device-id": dh.device.Id,
554 "duration": duration,
555 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400556 if duration == backoff.Stop {
557 // If we reach a maximum then warn and reset the backoff
558 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100559 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530560 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530561 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400562 indicationBackoff.Reset()
563 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700564
565 // On failure process a backoff timer while watching for stopIndications
566 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700567 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700568 select {
569 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000570 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700571 if !backoffTimer.Stop() {
572 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700573 }
574 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700575 case <-backoffTimer.C:
576 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700577 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700578 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
579 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400580 }
581 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100582 default:
583 if err != nil {
584 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530585 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530586 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100587 // Close the stream, and re-initialize it
588 if err = indications.CloseSend(); err != nil {
589 // Ok to ignore here, because we landed here due to a problem on the stream
590 // In all probability, the closeSend call may fail
591 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
592 log.Fields{"err": err,
593 "device-id": dh.device.Id})
594 }
595 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
596 return err
597 }
598 // once we re-initialized the indication stream, continue to read indications
599 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700600 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100601 // Reset backoff if we have a successful receive
602 indicationBackoff.Reset()
603 // When OLT is admin down, ignore all indications.
604 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
605 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
606 log.Fields{"indication": indication,
607 "device-id": dh.device.Id})
608 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700609 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100610 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530611 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700612 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700613 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700614 // Close the send stream
615 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700616
Girish Gowdra3f974912020-03-23 20:35:18 -0700617 return nil
618}
619
620func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700621 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700622 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
623 if err != nil {
624 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
625 }
626 if indications == nil {
627 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
628 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700629 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700630 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400631}
632
633// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
634func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
635 switch indication.Data.(type) {
636 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
637 return true
638
639 default:
640 return false
641 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700642}
643
David K. Bainbridge794735f2020-02-11 21:01:37 -0800644func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700645 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000646 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530647 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700648 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530649 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000651 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000652 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530653 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000654 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800655 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000656 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800657 }
658 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700659}
660
Akash Kankanala041a2122024-10-16 15:49:22 +0530661// nolint: gocyclo,govet
npujarec5762e2020-01-01 14:08:48 +0530662func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700663 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700664 switch indication.Data.(type) {
665 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000666 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
667 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700668 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 -0800669 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400670 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700672 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000673 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
674 defer span.Finish()
675
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700676 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800677 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100678 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400679 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800680 }
681 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000682 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700683 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000684 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
685 defer span.Finish()
686
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700687 intfOperInd := indication.GetIntfOperInd()
688 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800689 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100690 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400691 _ = 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 -0800692 }
693 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700694 } else if intfOperInd.GetType() == "pon" {
695 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
696 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800697 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100698 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400699 _ = 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 -0800700 }
701 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700703 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000704 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530705 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530706 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700707 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000708 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
709 defer span.Finish()
710
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700711 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000712 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530713 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800714 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700715 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000716 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
717 defer span.Finish()
718
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700719 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000720 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530721 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800722 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700723 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000724 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
725 defer span.Finish()
726
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700727 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000728 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 -0800729 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000730 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400731 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800732 }
733 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700734 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000735 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
736 defer span.Finish()
737
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700738 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000739 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700740 "intf-type": pktInd.IntfId,
741 "intf-id": pktInd.IntfId,
742 "gem-port-id": pktInd.GemportId,
743 "port-no": pktInd.PortNo,
744 "device-id": dh.device.Id,
745 })
746
747 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000748 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700749 "intf-type": pktInd.IntfId,
750 "intf-id": pktInd.IntfId,
751 "gem-port-id": pktInd.GemportId,
752 "port-no": pktInd.PortNo,
753 "packet": hex.EncodeToString(pktInd.Pkt),
754 "device-id": dh.device.Id,
755 })
756 }
757
David K. Bainbridge794735f2020-02-11 21:01:37 -0800758 go func() {
759 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400760 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800761 }
762 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700763 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000764 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
765 defer span.Finish()
766
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700767 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700768 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000770 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
771 defer span.Finish()
772
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700773 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000774 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700775 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000776 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
777 defer span.Finish()
778
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700779 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000780 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
781 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700782 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530783}
784
nikesh.krishnanc8473432023-06-14 12:14:54 +0530785func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
786 onuInd := &oop.OnuIndication{
787 IntfId: intfID,
788 OnuId: onuID,
789 OperState: operState,
790 AdminState: adminState,
791 }
792 indication := &oop.Indication{
793 Data: &oop.Indication_OnuInd{
794 OnuInd: onuInd,
795 },
796 }
797 return indication
798}
799
800func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
801 onuAlarmInd := &oop.OnuAlarmIndication{
802 IntfId: intfID,
803 OnuId: onuID,
804 LosStatus: losStatus,
805 }
806 alarmInd := &oop.AlarmIndication{
807 Data: &oop.AlarmIndication_OnuAlarmInd{
808 OnuAlarmInd: onuAlarmInd,
809 },
810 }
811 return alarmInd
812}
nikesh.krishnanc8473432023-06-14 12:14:54 +0530813
Akash Kankanala041a2122024-10-16 15:49:22 +0530814func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530815 ponlosAlarmInd := &oop.LosIndication{
816 IntfId: intfID,
817 Status: losStatus,
818 }
819 alarmInd := &oop.AlarmIndication{
820 Data: &oop.AlarmIndication_LosInd{
821 LosInd: ponlosAlarmInd,
822 },
823 }
824 return alarmInd
825}
Akash Kankanala041a2122024-10-16 15:49:22 +0530826
nikesh.krishnanc8473432023-06-14 12:14:54 +0530827func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
828 go func() {
829 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
830 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
831 }
832 }()
833
834 raisedTs := time.Now().Unix()
835 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
836}
837
838func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530839 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
840 if err != nil {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530841 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530842 return err
843 }
844 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530845 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
846 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
847 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
848
849 onuID := onuDeviceFromCore.ProxyAddress.OnuId
850 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
851 if err != nil {
852 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530853 } else {
854 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
855 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
856 switch {
857 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
858 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
859 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
860
861 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
Akash Kankanala041a2122024-10-16 15:49:22 +0530862 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") // check bal cli login notepad
nikesh.krishnanc8473432023-06-14 12:14:54 +0530863 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
864 raisedTs := time.Now().Unix()
865 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
866
867 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
868 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530869 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530870 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530871 return nil
872}
873
874func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
875 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
876 DeviceId: dh.device.Id,
877 PortType: voltha.Port_PON_OLT,
878 })
879 if err != nil {
880 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530881 return err
nikesh.krishnanc8473432023-06-14 12:14:54 +0530882 }
883 for _, portFromCore := range portsFromCore.Items {
884 portNum := portFromCore.GetPortNo()
885 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
886 portOperStatusFromCore := portFromCore.OperStatus
887 portAdminStateFromCore := portFromCore.AdminState
888 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
889 if err != nil {
890 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
891 } else {
892 portLosFromOlt := ponPortFromOlt.GetLos()
893 portStateFromOlt := ponPortFromOlt.GetState()
894 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
895 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
896 "portStateFromOlt": portStateFromOlt.String(),
897 "portOperStatusFromCore": portOperStatusFromCore.String(),
898 "device-id": dh.device.Id,
899 "port": portNum})
900 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
901 raisedTs := time.Now().Unix()
902 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530903 }
904 switch {
905 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
906 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
907 "portStateFromOlt": portStateFromOlt.String(),
908 "portOperStatusFromCore": portOperStatusFromCore.String(),
909 "device-id": dh.device.Id,
910 "port": portNum})
911 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
912 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
913 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
914 "portStateFromOlt": portStateFromOlt.String(),
915 "portOperStatusFromCore": portOperStatusFromCore.String(),
916 "device-id": dh.device.Id,
917 "port": portNum})
918 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
919 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
920 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
921 "device-id": dh.device.Id,
922 "port": portNum})
923 default:
924 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
925 "portStateFromOlt": portStateFromOlt.String(),
926 "portOperStatusFromCore": portOperStatusFromCore.String(),
927 "device-id": dh.device.Id,
928 "port": portNum})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530929 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530930 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530931 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530932 return nil
933}
934
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530935// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530936func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530937 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +0530938 // Declare deviceStateFilter to be used later
939 var deviceStateFilter *ca.DeviceStateFilter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000940 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530941 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +0530942 if err != nil {
943 return fmt.Errorf("failed to get device from core: %w", err)
944 }
945 logger.Info(ctx, "Device state", log.Fields{
946 "device-id": device.Id,
947 "CurrOperStatus": device.OperStatus,
948 "CurrConnStatus": device.ConnectStatus,
949 })
950 // Perform cleanup if the device's operational status is REBOOTED
951 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
952 // Log the device's operational status if it's REBOOTED
953 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
954 "device-id": device.Id,
955 "OperStatus": device.OperStatus,
956 })
957 dh.lockDevice.RLock()
958 // Stop the read indication only if it the routine is active
959 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
960 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
961 // on next execution of the readIndication routine.
962 if dh.isHeartbeatCheckActive {
963 dh.stopHeartbeatCheck <- true
964 }
965 if dh.isReadIndicationRoutineActive {
966 dh.stopIndications <- true
967 }
968 dh.lockDevice.RUnlock()
Akash Kankanala041a2122024-10-16 15:49:22 +0530969 if err = dh.cleanupDeviceResources(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +0530970 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
971 return fmt.Errorf("cleanup device resources failed: %w", err)
972 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530973 if err = dh.initializeDeviceHandlerModules(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +0530974 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
975 }
976 go startHeartbeatCheck(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +0530977 //dh.lockDevice.RUnlock()
Nandita Biradar1b590f12024-09-27 10:56:28 +0530978 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
979 // Log the device's operational status if it's RECONCILING
980 logger.Info(ctx, "Device is being reconciled", log.Fields{
981 "device-id": device.Id,
982 "OperStatus": device.OperStatus,
983 })
984
985 // Perform reconciliation steps
986 err = dh.reconcileOnus(ctx)
987 if err != nil {
988 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
989 }
990 err = dh.reconcilePonPorts(ctx)
991 if err != nil {
992 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530993 }
994 }
Girish Gowdra618fa572021-09-01 17:19:29 -0700995 // instantiate the mcast handler routines.
996 for i := range dh.incomingMcastFlowOrGroup {
997 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
998 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
999 if !dh.mcastHandlerRoutineActive[i] {
1000 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1001 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1002 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1003 // for incoming mcast flow/group to be processed serially.
1004 dh.mcastHandlerRoutineActive[i] = true
1005 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1006 }
1007 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301008 // Create DeviceStateFilter with the desired operational and connection statuses
1009 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001010 DeviceId: dh.device.Id,
1011 OperStatus: voltha.OperStatus_ACTIVE,
1012 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301013 }
1014 // Log DeviceStateFilter for debugging purposes
1015 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1016 "DeviceId": deviceStateFilter.DeviceId,
1017 "OperStatus": deviceStateFilter.OperStatus,
1018 "ConnStatus": deviceStateFilter.ConnStatus,
1019 })
1020 // Synchronous call to update device state - this method is run in its own go routine
balaji6299cb23cbe2025-04-14 17:53:10 +05301021 if err = dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001022 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001023 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001024
Akash Kankanala041a2122024-10-16 15:49:22 +05301025 // Clear olt communication failure event
Gamze Abaka07868a52020-12-17 14:19:28 +00001026 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1027 dh.device.OperStatus = voltha.OperStatus_ACTIVE
balaji6299cb23cbe2025-04-14 17:53:10 +05301028
1029 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
1030 if err != nil {
1031 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
1032 }
1033 dh.populateActivePorts(ctx, ports.Items)
1034 if err = dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1035 logger.Error(ctx, "port-status-update-failed", log.Fields{"error": err, "ports": ports})
1036 }
1037
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001038 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001039 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1040
Girish Gowdru0c588b22019-04-23 23:24:56 -04001041 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301042}
1043
1044// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301045func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001046 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001047
khenaidoo106c61a2021-08-11 18:05:46 -04001048 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001049 if err != nil || device == nil {
1050 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001051 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001052 }
1053
1054 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001055
Akash Kankanala041a2122024-10-16 15:49:22 +05301056 // Update the device oper state and connection status
Girish Gowdrud4245152019-05-10 00:47:31 -04001057 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001058 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001059 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001060 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001061
khenaidoodc2116e2021-10-19 17:33:19 -04001062 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001063 DeviceId: cloned.Id,
1064 OperStatus: cloned.OperStatus,
1065 ConnStatus: cloned.ConnectStatus,
1066 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001067 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001068 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001069
Akash Kankanala041a2122024-10-16 15:49:22 +05301070 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001071 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001072 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001073 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001074 }
1075 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001076 // Update onu state as down in onu adapter
1077 onuInd := oop.OnuIndication{}
1078 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001079
1080 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1081 if err != nil {
1082 return err
1083 }
1084 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001085 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001086 DeviceId: onuDevice.Id,
1087 OnuIndication: &onuInd,
1088 })
1089 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001091 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001092 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 "onu-indicator": onuInd,
1094 "device-type": onuDevice.Type,
1095 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301096 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001097 } else {
1098 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 -07001099 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001100 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001101 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001102 /* Discovered ONUs entries need to be cleared , since after OLT
1103 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301104 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001105 dh.lockDevice.Unlock()
1106
Neha Sharma96b7bf22020-06-15 10:37:32 +00001107 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001108 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301109}
1110
1111// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301112func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001113 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001114
1115 // if the connection is already available, close the previous connection (olt reboot case)
1116 if dh.clientCon != nil {
1117 if err = dh.clientCon.Close(); err != nil {
1118 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1119 } else {
1120 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1121 }
1122 }
1123
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301124 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +00001125 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001126 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1127 grpc.WithInsecure(),
1128 grpc.WithBlock(),
1129 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001130 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001131 )),
1132 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001133 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001134 )))
1135
1136 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301137 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301138 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001139 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001140 }
Akash Sonif49299a2024-04-25 12:06:37 +05301141 //Setting oper and connection state to RECONCILING and conn state to reachable
1142 cgClient, err := dh.coreClient.GetCoreServiceClient()
1143 if err != nil {
1144 return err
1145 }
1146
1147 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1148 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1149 defer cancel()
1150 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1151 DeviceId: dh.device.Id,
1152 OperStatus: voltha.OperStatus_RECONCILING,
1153 ConnStatus: voltha.ConnectStatus_REACHABLE,
1154 }); err != nil {
1155 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1156 }
1157 // 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
1158 // locally cached copy of the device struct.
1159 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1160 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1161 }
1162
Girish Gowdru0c588b22019-04-23 23:24:56 -04001163 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301164}
1165
1166// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301167func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001168 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301169 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001170 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301171}
1172
1173// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301174func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301175 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001176 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001177
1178 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001179 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301180 if err != nil || device == nil {
1181 /*TODO: needs to handle error scenarios */
1182 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1183 }
1184 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001185 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001186
1187 cloned := proto.Clone(device).(*voltha.Device)
1188 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1189 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1190 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001191
khenaidoodc2116e2021-10-19 17:33:19 -04001192 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001193 DeviceId: cloned.Id,
1194 OperStatus: cloned.OperStatus,
1195 ConnStatus: cloned.ConnectStatus,
1196 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301197 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 -04001198 }
1199
Chaitrashree G S44124192019-08-07 20:21:36 -04001200 // 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 +05301201 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001202 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301203 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001204 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001205 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1206 // all the modules initialized and ready to handle incoming ONUs.
1207
Thomas Lee S985938d2020-05-04 11:40:41 +05301208 err = dh.initializeDeviceHandlerModules(ctx)
1209 if err != nil {
1210 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 -04001211 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001212
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001213 go startHeartbeatCheck(ctx, dh)
1214
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001215 return nil
1216 }
1217
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001218 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301219 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 -04001220 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301221
Neha Sharma96b7bf22020-06-15 10:37:32 +00001222 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001223
1224 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001225 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001226 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001227
1228 go startHeartbeatCheck(ctx, dh)
1229
cuilin20187b2a8c32019-03-26 19:52:28 -07001230 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301231}
1232
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001233func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001234 var err error
1235 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001236
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001237 if dh.flowMgr != nil {
1238 dh.StopAllFlowRoutines(ctx)
1239 }
1240
1241 dh.CloseKVClient(ctx)
1242
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001243 if err != nil {
1244 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1245 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001246 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1247 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +00001248 // +1 is for NNI
1249 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1250 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001251 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001252 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1253 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1254 // There is only one NNI manager since multiple NNI is not supported for now
1255 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001256 // Instantiate resource manager
1257 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 -07001258 return olterrors.ErrResourceManagerInstantiating
1259 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001260 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001261 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1262 // the KV store to manage mcast group data. Provide the first instance (0th index)
1263 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1264 return olterrors.ErrGroupManagerInstantiating
1265 }
yasin saplid0566272021-12-21 09:10:30 +00001266 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001267 // Instantiate flow manager
1268 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301269 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001270 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1271 } else {
1272 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001273 }
1274 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001275 /* TODO: Instantiate Alarm , stats , BW managers */
1276 /* Instantiating Event Manager to handle Alarms and KPIs */
1277 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1278
1279 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001280 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001281
1282 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001283}
1284
Neha Sharma96b7bf22020-06-15 10:37:32 +00001285func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001286 var err error
1287 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301288 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001289
Neha Sharma8f4e4322020-08-06 10:51:53 +00001290 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001291
1292 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001293 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001294 }
1295 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001296 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001297 }
1298
Neha Sharma96b7bf22020-06-15 10:37:32 +00001299 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001300 dh.device.Root = true
1301 dh.device.Vendor = deviceInfo.Vendor
1302 dh.device.Model = deviceInfo.Model
1303 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1304 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1305 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1306
1307 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001308 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001309 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301310 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001311 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001312 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001313 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001314 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001315 dh.device.MacAddress = genmac
1316 } else {
1317 dh.device.MacAddress = deviceInfo.DeviceId
1318 }
1319
1320 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001321 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001322 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001323 }
1324
1325 return deviceInfo, nil
1326}
1327
Neha Sharma96b7bf22020-06-15 10:37:32 +00001328func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001329 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001330
1331 defer func() {
1332 dh.lockDevice.Lock()
1333 dh.isCollectorActive = false
1334 dh.lockDevice.Unlock()
1335 }()
1336
1337 dh.lockDevice.Lock()
1338 dh.isCollectorActive = true
1339 dh.lockDevice.Unlock()
1340
Naga Manjunath7615e552019-10-11 22:35:47 +05301341 for {
1342 select {
1343 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001344 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301345 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001346 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001347
khenaidoo106c61a2021-08-11 18:05:46 -04001348 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001349 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001350 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001351 continue
1352 }
khenaidoo106c61a2021-08-11 18:05:46 -04001353 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301354 // NNI Stats
1355 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001356 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301357 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001358 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001359 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001360 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301361 }
1362 // PON Stats
1363 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001364 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301365 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1366 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001367 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001368 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301369 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001370 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001371
yasin sapli9e4c5092022-02-01 13:52:33 +00001372 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001373 if len(onuGemInfoLst) > 0 {
1374 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001375 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001376 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301377 }
1378 }
1379 }
1380}
1381
Mahir Gunyela2e68702022-12-07 00:00:42 -08001382// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301383func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001384 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001385 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301386 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301387
1388 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001389 cgClient, err := dh.coreClient.GetCoreServiceClient()
1390 if err != nil {
1391 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1392 return
1393 }
1394
1395 // Now, set the initial PM configuration for that device
1396 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001397 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301398 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301399}
1400
Mahir Gunyela2e68702022-12-07 00:00:42 -08001401// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001402func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1403 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001404 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301405 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001406 HwDesc: "open_pon",
1407 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001408 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001409 },
1410 SwitchFeatures: &of.OfpSwitchFeatures{
1411 NBuffers: 256,
1412 NTables: 2,
1413 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1414 of.OfpCapabilities_OFPC_TABLE_STATS |
1415 of.OfpCapabilities_OFPC_PORT_STATS |
1416 of.OfpCapabilities_OFPC_GROUP_STATS),
1417 },
1418 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301419}
1420
khenaidoo106c61a2021-08-11 18:05:46 -04001421// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001422func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001423 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001424 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001425 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001426 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001427 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1428 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()
1429 }
khenaidoo106c61a2021-08-11 18:05:46 -04001430 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001431}
1432
Neha Sharma96b7bf22020-06-15 10:37:32 +00001433func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001434 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 -07001435 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001436 var deviceID string
1437 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001438 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001439
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001440 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001441 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001442 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 -07001443 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1444 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001445
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001446 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301447
1448 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001449 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 -07001450 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001451
khenaidoodc2116e2021-10-19 17:33:19 -04001452 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001453 ParentId: dh.device.Id,
1454 OnuId: omciInd.OnuId,
1455 ParentPortNo: ponPort,
1456 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001457 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301458 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001459 "intf-id": omciInd.IntfId,
1460 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001461 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001462 deviceType = onuDevice.Type
1463 deviceID = onuDevice.Id
1464 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001465 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301466 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001467 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001468 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301469 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001470 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 +05301471 deviceType = onuInCache.(*OnuDevice).deviceType
1472 deviceID = onuInCache.(*OnuDevice).deviceID
1473 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001474 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001475 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001476
khenaidoodc2116e2021-10-19 17:33:19 -04001477 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001478 ParentDeviceId: proxyDeviceID,
1479 ChildDeviceId: deviceID,
1480 Message: omciInd.Pkt,
1481 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301482 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001483 "source": dh.openOLT.config.AdapterEndpoint,
1484 "device-type": deviceType,
1485 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001486 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001487 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001488 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001489 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301490}
1491
khenaidoo106c61a2021-08-11 18:05:46 -04001492// //ProcessInterAdapterMessage sends the proxied messages to the target device
1493// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1494// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001495// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001496// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001497// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001498// return dh.handleInterAdapterOmciMsg(ctx, msg)
1499// }
1500// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1501// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001502
kesavandb9f54fd2021-11-25 20:08:04 +05301503// ProxyOmciRequests sends the proxied OMCI message to the target device
1504func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301505 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1506 return status.Error(codes.Unavailable, "OLT unreachable")
1507 }
kesavandb9f54fd2021-11-25 20:08:04 +05301508 if omciMsgs.GetProxyAddress() == nil {
1509 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1510 if err != nil {
1511 return olterrors.NewErrNotFound("onu", log.Fields{
1512 "parent-device-id": dh.device.Id,
1513 "child-device-id": omciMsgs.ChildDeviceId}, err)
1514 }
1515 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1516 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1517 return olterrors.NewErrCommunication("send-failed", log.Fields{
1518 "parent-device-id": dh.device.Id,
1519 "child-device-id": omciMsgs.ChildDeviceId}, err)
1520 }
1521 } else {
1522 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1523 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1524 return olterrors.NewErrCommunication("send-failed", log.Fields{
1525 "parent-device-id": dh.device.Id,
1526 "child-device-id": omciMsgs.ChildDeviceId}, err)
1527 }
1528 }
1529 return nil
1530}
1531
1532func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1533 var intfID uint32
1534 var onuID uint32
1535 var connectStatus common.ConnectStatus_Types
1536 if onuDevice != nil {
1537 intfID = onuDevice.ProxyAddress.GetChannelId()
1538 onuID = onuDevice.ProxyAddress.GetOnuId()
1539 connectStatus = onuDevice.ConnectStatus
1540 } else {
1541 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1542 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1543 connectStatus = omciMsgs.GetConnectStatus()
1544 }
1545 if connectStatus != voltha.ConnectStatus_REACHABLE {
1546 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1547
1548 return olterrors.NewErrCommunication("unreachable", log.Fields{
1549 "intf-id": intfID,
1550 "onu-id": onuID}, nil)
1551 }
1552
1553 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1554 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1555
1556 onuSecOmciMsgList := omciMsgs.GetMessages()
1557
1558 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301559 var omciMessage *oop.OmciMsg
1560 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1561 hex.Encode(hexPkt, onuSecOmciMsg)
1562 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1563
1564 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1565 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1566 //https://jira.opencord.org/browse/VOL-4604
1567 transid := extractOmciTransactionID(onuSecOmciMsg)
1568 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1569 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1570
1571 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1572 if err != nil {
1573 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1574 "intf-id": intfID,
1575 "onu-id": onuID,
1576 "message": omciMessage}, err)
1577 }
1578 }
1579 return nil
1580}
1581
khenaidoo106c61a2021-08-11 18:05:46 -04001582// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001583func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001584 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 -07001585
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301586 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1587 return status.Error(codes.Unavailable, "OLT unreachable")
1588 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001589 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001590 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001591 if err != nil {
1592 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001593 "parent-device-id": dh.device.Id,
1594 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001595 }
khenaidoo106c61a2021-08-11 18:05:46 -04001596 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1597 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001598 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001599 "parent-device-id": dh.device.Id,
1600 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001601 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001602 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001603 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1604 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001605 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001606 "parent-device-id": dh.device.Id,
1607 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001608 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001609 }
1610 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301611}
1612
khenaidoodc2116e2021-10-19 17:33:19 -04001613func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001614 var intfID uint32
1615 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001616 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001617 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001618 intfID = onuDevice.ProxyAddress.GetChannelId()
1619 onuID = onuDevice.ProxyAddress.GetOnuId()
1620 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001621 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001622 intfID = omciMsg.GetProxyAddress().GetChannelId()
1623 onuID = omciMsg.GetProxyAddress().GetOnuId()
1624 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001625 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001626 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001627 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 -08001628
Thomas Lee S94109f12020-03-03 16:39:29 +05301629 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001630 "intf-id": intfID,
1631 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001632 }
1633
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001634 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1635 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301636 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001637 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001638 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1639 hex.Encode(hexPkt, omciMsg.Message)
1640 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1641
1642 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1643 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1644 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001645 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001646 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001647
Neha Sharma8f4e4322020-08-06 10:51:53 +00001648 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001649 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301650 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001651 "intf-id": intfID,
1652 "onu-id": onuID,
1653 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001654 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001655 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001656}
1657
David K. Bainbridge794735f2020-02-11 21:01:37 -08001658func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301659 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 +00001660 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001661 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001662 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001663 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301664 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301665 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001666 st, _ := status.FromError(err)
1667 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001668 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 -04001669 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301670 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001671 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001672 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001674 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001675 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001676}
1677
Mahir Gunyela2e68702022-12-07 00:00:42 -08001678// getChildDevice function can be used in general to get child device, if not found in cache the function will
1679// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301680func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1681 var InCacheOnuDev *OnuDevice
1682 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1683 if onuInCache.(*OnuDevice).serialNumber == sn {
1684 InCacheOnuDev = onuInCache.(*OnuDevice)
1685 return false
1686 }
1687 return true
1688 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301689 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301690 if InCacheOnuDev != nil {
1691 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1692 return InCacheOnuDev
1693 }
1694 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1695 ParentId: dh.device.Id,
1696 SerialNumber: sn,
1697 ParentPortNo: parentPortNo,
1698 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301699 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301700 if onuDevice == nil {
1701 return nil
1702 }
1703 onuID := onuDevice.ProxyAddress.OnuId
1704 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1705 onuKey := dh.formOnuKey(intfID, onuID)
1706
1707 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1708 dh.onus.Store(onuKey, onuDev)
1709 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1710 return onuDev
1711}
1712
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301713// checkForResourceExistance checks for either device in rw-core or active techprofile in olt-adapter, based on the flag CheckOnuDevExistenceAtOnuDiscovery.
1714// If the ONU device/resource exists in either of these, the ONU discovery will be ignored.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301715func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001716 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Akash Kankanala041a2122024-10-16 15:49:22 +05301717 // 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 +05301718 // 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 +05301719 if dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1720 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1721 ParentId: dh.device.Id,
1722 SerialNumber: sn,
1723 ParentPortNo: parentPortNo,
1724 })
1725 if onuDevice != nil {
1726 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1727 return true, nil
1728 }
1729 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1730
1731 return false, nil
1732 } else {
1733 tpInstExists := false
1734 channelID := onuDiscInd.GetIntfId()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301735 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1736 if onuDev != nil {
1737 var onuGemInfo *rsrcMgr.OnuGemInfo
1738 var err error
1739 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1740 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1741 return false, err
1742 }
1743 if onuGemInfo != nil {
1744 for _, uni := range onuGemInfo.UniPorts {
1745 uniID := plt.UniIDFromPortNum(uni)
1746 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1747 if len(tpIDs) != 0 {
1748 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1749 tpInstExists = true
1750 break
1751 }
1752 }
1753 }
1754 }
1755 return tpInstExists, nil
1756 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301757}
1758
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001759// processDiscONULOSClear clears the LOS Alarm if it's needed
1760func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301761 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001762 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301763
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001764 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1765 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1766 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1767 OnuLosRaise event sent for it */
1768 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1769 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1770 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1771 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1772 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1773 "currentIntfId": onuDiscInd.GetIntfId()})
1774 // TODO:: Should we need to ignore raising OnuLosClear event
1775 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301776 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001777 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1778 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1779 alarmInd.LosStatus = statusCheckOff
1780 go func() {
1781 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1782 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1783 }
1784 }()
1785 // stop iterating
1786 return false
1787 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301788 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001789 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301790}
1791
bseeniva43b5a912025-06-05 12:48:15 +05301792func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1793 if err != nil || tpInstExists {
1794 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1795 } else {
1796 // once the function completes set the value to false so that
1797 // we know the processing has inProcess.
1798 // Note that this is done after checking if we are already processing
1799 // to avoid changing the value from a different thread
1800 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1801 dh.discOnus.Store(sn, false)
1802 }
1803}
1804
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301805func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301806 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301807 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301808
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301809 channelID := onuDiscInd.GetIntfId()
1810 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1811
1812 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301813 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301814 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301815 }()
1816
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301817 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1818
Sridhar Ravindraab785f22025-07-21 17:20:55 +05301819 // Check for resource existence only if the ForceOnuDiscIndProcessing is disabled.
1820 if !dh.cfg.ForceOnuDiscIndProcessing {
1821 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1822 if error != nil {
1823 return error
1824 }
1825 if tpInstExists {
1826 // ignore the discovery if tpinstance is present.
1827 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
1828 return nil
1829 }
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001830 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001831 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1832
1833 // if the ONU existed, handle the LOS Alarm
1834 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001835 if inProcess.(bool) {
1836 // if we're currently processing the ONU on a different thread, do nothing
1837 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1838 return nil
1839 }
1840 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1841 // then continue processing it
1842 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1843
1844 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001845 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301846 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001847 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001848
1849 // check the ONU is already know to the OLT
1850 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301851 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001852 ParentId: dh.device.Id,
1853 SerialNumber: sn,
1854 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001855
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301856 if error != nil {
1857 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1858 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001859 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 -08001860 switch e.Code() {
1861 case codes.Internal:
1862 // this probably means NOT FOUND, so just create a new device
1863 onuDevice = nil
1864 case codes.DeadlineExceeded:
1865 // if the call times out, cleanup and exit
1866 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301867 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1868 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001869 }
1870 }
1871 }
1872
1873 if onuDevice == nil {
1874 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001876 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001877 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301878 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001879 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001880
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301881 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001882 // if we can't create an ID in resource manager,
1883 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001884 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301885
1886 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001887 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301888 "serial-number": sn}, error)
1889 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001890 }
1891
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301892 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001893 ParentId: dh.device.Id,
1894 ParentPortNo: parentPortNo,
1895 ChannelId: channelID,
1896 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1897 SerialNumber: sn,
1898 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301899 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001900 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001901 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 +05301902
1903 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001904 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301905 "serial-number": sn}, error)
1906 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001907 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301908 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 +05301909 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
1910 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
1911 "onu-id": onuID,
1912 "device-id": dh.device.Id,
1913 "serial-number": sn}, error)
1914 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04001915 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001916 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301917 log.Fields{"onuDevice": onuDevice,
1918 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001919 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301920 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001921 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001922
khenaidoo106c61a2021-08-11 18:05:46 -04001923 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1924 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301925 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04001926 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301927 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301928 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
1929 return error
khenaidoo106c61a2021-08-11 18:05:46 -04001930 }
1931
Matteo Scandolo945e4012019-12-12 14:16:11 -08001932 // we can now use the existing ONU Id
1933 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05301934 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07001935 //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 +00001936 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001937 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301938 "intfId": onuDiscInd.GetIntfId(),
1939 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001940 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001941
khenaidoo106c61a2021-08-11 18:05:46 -04001942 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301943 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001944 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301945 log.Fields{"onu": onuDev,
1946 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001947
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301948 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001949 DeviceId: onuDevice.Id,
1950 ParentDeviceId: dh.device.Id,
1951 OperStatus: common.OperStatus_DISCOVERED,
1952 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301953 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301954 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001955 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301956 "serial-number": sn}, error)
1957 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07001958 }
khenaidoo106c61a2021-08-11 18:05:46 -04001959
Neha Sharma96b7bf22020-06-15 10:37:32 +00001960 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301961 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301962 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001963 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301964 "serial-number": sn}, error)
1965 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08001966 }
1967 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001968}
1969
Mahir Gunyelb0046752021-02-26 13:51:05 -08001970func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001971 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001972 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001973 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001974 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001975 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301976 log.Fields{"onuId": onuInd.OnuId,
1977 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301978 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001979 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001980 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001981 errFields := log.Fields{"device-id": dh.device.Id}
1982
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301983 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05301984 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07001985 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001986 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001987 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001988 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301989 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07001990 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001991 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001992 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001993 errFields["onu-id"] = onuInd.OnuId
1994 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001995 }
khenaidoodc2116e2021-10-19 17:33:19 -04001996 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001997 ParentId: dh.device.Id,
1998 SerialNumber: serialNumber,
1999 OnuId: onuInd.OnuId,
2000 ParentPortNo: ponPort,
2001 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002002 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002003
David K. Bainbridge794735f2020-02-11 21:01:37 -08002004 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002005 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002006 }
2007
David K. Bainbridge794735f2020-02-11 21:01:37 -08002008 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002009 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002010 "previousIntfId": onuDevice.ParentPortNo,
2011 "currentIntfId": ponPort})
2012 }
2013
2014 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002015 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302016 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2017 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302018 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002019 }
2020 if !foundInCache {
2021 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002022 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 -08002023 }
kesavand7cf3a052020-08-28 12:49:18 +05302024 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002025 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002026 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302027 }
2028 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002029 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002030 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002031 }
2032 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002033}
2034
Neha Sharma96b7bf22020-06-15 10:37:32 +00002035func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002036 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 -07002037 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2038 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2039 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2040 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002041 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002042 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2043 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002044 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002045 onuInd.OperState = "down"
2046 }
2047 }
2048
David K. Bainbridge794735f2020-02-11 21:01:37 -08002049 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002050 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002051 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 -04002052
khenaidoodc2116e2021-10-19 17:33:19 -04002053 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002054 DeviceId: onuDevice.Id,
2055 OnuIndication: onuInd,
2056 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002057 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302058 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002059 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002060 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002061 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002062 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002063 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002064 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002065 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002066 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002067 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002068}
2069
cuilin20187b2a8c32019-03-26 19:52:28 -07002070func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2071 if serialNum != nil {
2072 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002073 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002074 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002075}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002076func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2077 decodedStr, err := hex.DecodeString(serialNum[4:])
2078 if err != nil {
2079 return nil, err
2080 }
2081 return &oop.SerialNumber{
2082 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002083 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002084 }, nil
2085}
cuilin20187b2a8c32019-03-26 19:52:28 -07002086
2087func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002088 if len(vendorSpecific) > 3 {
2089 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2090 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2091 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2092 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2093 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2094 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2095 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2096 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2097 return tmp
2098 }
2099 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002100}
2101
Mahir Gunyela2e68702022-12-07 00:00:42 -08002102// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002103func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302104 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002105}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002106
Mahir Gunyela2e68702022-12-07 00:00:42 -08002107// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002108func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2109 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302110 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002111 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302112 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002113
khenaidoodc2116e2021-10-19 17:33:19 -04002114 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002115 ParentId: dh.device.Id,
2116 OnuId: onuID,
2117 ParentPortNo: parentPort,
2118 })
2119
Girish Gowdru0c588b22019-04-23 23:24:56 -04002120 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002121 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002122 "intf-id": parentPort,
2123 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002124 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125 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 -08002126 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302127}
2128
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002129// SendPacketInToCore sends packet-in to core
2130// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2131// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002132func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002133 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002134 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002135 "port": logicalPort,
2136 "packet": hex.EncodeToString(packetPayload),
2137 "device-id": dh.device.Id,
2138 })
2139 }
khenaidoo106c61a2021-08-11 18:05:46 -04002140
khenaidoodc2116e2021-10-19 17:33:19 -04002141 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002142 DeviceId: dh.device.Id,
2143 Port: logicalPort,
2144 Packet: packetPayload,
2145 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302146 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002147 "source": "adapter",
2148 "destination": "core",
2149 "device-id": dh.device.Id,
2150 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002151 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002152 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002153 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002154 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002155 "packet": hex.EncodeToString(packetPayload),
2156 "device-id": dh.device.Id,
2157 })
2158 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002159 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002160}
2161
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002162// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002163func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002164 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002165
2166 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2167 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002168 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002169 }
2170
Kent Hagermane6ff1012020-07-14 15:07:53 -04002171 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002172 metrics := dh.metrics.GetSubscriberMetrics()
2173 for _, m := range pmConfigs.Metrics {
2174 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002175 }
2176 }
2177}
2178
khenaidoodc2116e2021-10-19 17:33:19 -04002179func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002180 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002181 var errorsList []error
2182
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002183 if dh.getDeviceDeletionInProgressFlag() {
2184 // The device itself is going to be reset as part of deletion. So nothing to be done.
2185 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2186 return nil
2187 }
2188
Girish Gowdru0c588b22019-04-23 23:24:56 -04002189 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002190 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302191 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002192
Neha Sharma96b7bf22020-06-15 10:37:32 +00002193 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302194 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002195 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302196 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002197 if flow_utils.HasGroup(flow) {
2198 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2199 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002200 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2201 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2202 } else {
2203 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2204 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002205 }
Girish Gowdracefae192020-03-19 18:14:10 -07002206 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002207 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302208 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002209 logger.Warnw(ctx, "flow-to-remove-not-found",
2210 log.Fields{
2211 "ponIf": intfID,
2212 "flowToRemove": flow,
2213 "error": err,
2214 })
2215 } else {
2216 errorsList = append(errorsList, err)
2217 }
Girish Gowdracefae192020-03-19 18:14:10 -07002218 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002219 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302220
2221 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302222 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002223 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302224 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002225 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302226 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002227 if flow_utils.HasGroup(flow) {
2228 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2229 } else {
yasin saplid0566272021-12-21 09:10:30 +00002230 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002231 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2232 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2233 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2234 } else {
yasin saplid0566272021-12-21 09:10:30 +00002235 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002236 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002237 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002238 if err != nil {
2239 errorsList = append(errorsList, err)
2240 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302241 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002242 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002243
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002244 return errorsList
2245}
2246
2247func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2248 var err error
2249 var errorsList []error
2250
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002251 if dh.getDeviceDeletionInProgressFlag() {
2252 // The device itself is going to be reset as part of deletion. So nothing to be done.
2253 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2254 return nil
2255 }
2256
Girish Gowdracefae192020-03-19 18:14:10 -07002257 // 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 +00002258 if groups != nil {
2259 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002260 // err = dh.groupMgr.AddGroup(ctx, group)
2261 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002262 if err != nil {
2263 errorsList = append(errorsList, err)
2264 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002265 }
2266 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002267 // err = dh.groupMgr.ModifyGroup(ctx, group)
2268 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002269 if err != nil {
2270 errorsList = append(errorsList, err)
2271 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002272 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002273 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002274 // err = dh.groupMgr.DeleteGroup(ctx, group)
2275 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002276 if err != nil {
2277 errorsList = append(errorsList, err)
2278 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002279 }
2280 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002281
2282 return errorsList
2283}
2284
Mahir Gunyela2e68702022-12-07 00:00:42 -08002285// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002286func (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 -07002287 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002288
2289 if dh.getDeviceDeletionInProgressFlag() {
2290 // The device itself is going to be reset as part of deletion. So nothing to be done.
2291 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2292 return nil
2293 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302294 if dh.transitionMap.currentDeviceState != deviceStateUp {
2295 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2296 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2297 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002298 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2299 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2300 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002301 if len(errorsList) > 0 {
2302 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2303 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002304 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002305 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302306}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002307
Mahir Gunyela2e68702022-12-07 00:00:42 -08002308// DisableDevice disables the given device
2309// It marks the following for the given device:
2310// Device-Handler Admin-State : down
2311// Device Port-State: UNKNOWN
2312// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002313func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002314 /* On device disable ,admin state update has to be done prior sending request to agent since
2315 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002316 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002317 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002318 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002319 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002320 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002321 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002322 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002323 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002324 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002325 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302326
2327 dh.discOnus = sync.Map{}
2328 dh.onus = sync.Map{}
2329
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002330 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302331 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002332 if dh.isCollectorActive {
2333 dh.stopCollector <- true
2334 }
2335 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302336
Neha Sharma96b7bf22020-06-15 10:37:32 +00002337 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002338 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302339 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302340 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002341
kdarapu1afeceb2020-02-12 01:38:09 -05002342 // 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 -04002343 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002344 DeviceId: cloned.Id,
2345 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2346 OperStatus: voltha.OperStatus_UNKNOWN,
2347 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002348 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002349 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002350 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002351 return nil
2352}
2353
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002355 // Update onu state as unreachable in onu adapter
2356 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302357 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002358
Akash Kankanala041a2122024-10-16 15:49:22 +05302359 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002360 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002361 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002362 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 -04002363 }
2364 if onuDevices != nil {
2365 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002366 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002367 DeviceId: onuDevice.Id,
2368 OnuIndication: &onuInd,
2369 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002370 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002371 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002372 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002373 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002374 }
2375 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002376}
2377
Mahir Gunyela2e68702022-12-07 00:00:42 -08002378// ReenableDevice re-enables the olt device after disable
2379// It marks the following for the given device:
2380// Device-Handler Admin-State : up
2381// Device Port-State: ACTIVE
2382// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002383func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302384 if dh.Client != nil {
2385 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2386 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2387 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2388 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302389 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302390 } else {
2391 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 +05302392 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002393 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002394
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002395 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002396 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002397 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002398 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002399 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2400 } else {
2401 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2402 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2403 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002404 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002405 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302406 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002407 device.OperStatus = voltha.OperStatus_ACTIVE
2408 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302409 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002410 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002411 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002412 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002413
khenaidoodc2116e2021-10-19 17:33:19 -04002414 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002415 DeviceId: device.Id,
2416 OperStatus: device.OperStatus,
2417 ConnStatus: device.ConnectStatus,
2418 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302419 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002420 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002421 "connect-status": device.ConnectStatus,
2422 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002423 }
kesavand39e0aa32020-01-28 20:58:50 -05002424
Neha Sharma96b7bf22020-06-15 10:37:32 +00002425 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002426
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002427 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002428}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002429
npujarec5762e2020-01-01 14:08:48 +05302430func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002431 var uniID uint32
2432 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002433 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302434 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002435 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002436 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002437 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002438 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2439 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2440 } else {
2441 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2442 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002443 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002444 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002445 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002446 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002447 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002448 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002449 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002450 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002451 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002452 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002453 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002454 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002455 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002456 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002457 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002458 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302459 }
yasin saplibddc2d72022-02-08 13:10:17 +00002460 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2461 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002462 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002463 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302464 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002465 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002466 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002467 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 -03002468 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002469 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002470 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002471 if len(errs) > 0 {
2472 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2473 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2474 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002475 return nil
2476}
2477
Devmalya Paul495b94a2019-08-27 19:42:00 -04002478// 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 +05302479func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002480 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002481 /* Clear the KV store data associated with the all the UNI ports
2482 This clears up flow data and also resource map data for various
2483 other pon resources like alloc_id and gemport_id
2484 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002485
2486 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002487 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002488
Himani Chawla49a5d562020-11-25 11:53:44 +05302489 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002490 // Stop the Stats collector
2491 if dh.isCollectorActive {
2492 dh.stopCollector <- true
2493 }
2494 // stop the heartbeat check routine
2495 if dh.isHeartbeatCheckActive {
2496 dh.stopHeartbeatCheck <- true
2497 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302498 // Stop the read indication only if it the routine is active
2499 if dh.isReadIndicationRoutineActive {
2500 dh.stopIndications <- true
2501 }
2502 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302503
2504 err := dh.cleanupDeviceResources(ctx)
2505 if err != nil {
2506 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2507 } else {
2508 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2509 }
2510
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002511 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302512 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002513 if dh.Client != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302514 if _, err = dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002515 go func() {
2516 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302517 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2518 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002519 }
2520 }()
2521 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002522 }
2523 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002524 // There is no need to update the core about operation status and connection status of the OLT.
2525 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2526 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2527 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002528
khenaidoo7eb2d672021-10-22 19:08:50 -04002529 // Stop the adapter grpc clients for that parent device
2530 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002531 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002532}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002533
2534// StopAllFlowRoutines stops all flow routines
2535func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2536 var wg sync.WaitGroup
2537 wg.Add(1) // for the mcast routine below to finish
2538 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2539 for _, flMgr := range dh.flowMgr {
2540 if flMgr != nil {
2541 wg.Add(1) // for the flow handler routine below to finish
2542 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2543 }
2544 }
2545 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2546 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2547 } else {
2548 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2549 }
2550}
2551
Gustavo Silva41af9122022-10-11 11:05:13 -03002552func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2553 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002554 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302555 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002556 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002557 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002558 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002559 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002560 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2561 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302562 }
2563 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002564 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2565 errs = append(errs, err)
2566 }
2567 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2568 errs = append(errs, err)
2569 }
2570 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2571 errs = append(errs, err)
2572 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002573 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002574 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002575 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002576 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002577 }
2578 // Clean up NNI manager's data
2579 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2580 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002581 }
A R Karthick1f85b802019-10-11 05:06:05 +00002582
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002583 dh.CloseKVClient(ctx)
2584
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002585 // Take one final sweep at cleaning up KV store for the OLT device
2586 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002587 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2588 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002589 }
2590
Devmalya Paul495b94a2019-08-27 19:42:00 -04002591 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302592 dh.onus.Range(func(key interface{}, value interface{}) bool {
2593 dh.onus.Delete(key)
2594 return true
2595 })
2596
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002597 /*Delete discovered ONU map for the device*/
2598 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2599 dh.discOnus.Delete(key)
2600 return true
2601 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002602 if len(errs) > 0 {
2603 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2604 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2605 }
2606 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002607}
2608
Mahir Gunyela2e68702022-12-07 00:00:42 -08002609// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002610func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302611 if dh.Client != nil {
2612 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2613 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2614 }
2615 } else {
2616 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 -04002617 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302618
Neha Sharma96b7bf22020-06-15 10:37:32 +00002619 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002620 return nil
2621}
2622
David K. Bainbridge794735f2020-02-11 21:01:37 -08002623func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002624 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002625 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002626 "packet-indication": *packetIn,
2627 "device-id": dh.device.Id,
2628 "packet": hex.EncodeToString(packetIn.Pkt),
2629 })
2630 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002631 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2632 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2633 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002634 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002635 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002636 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002637 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002638 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002639 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002640 "logical-port-num": logicalPortNum,
2641 "device-id": dh.device.Id,
2642 "packet": hex.EncodeToString(packetIn.Pkt),
2643 })
2644 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002645
khenaidoodc2116e2021-10-19 17:33:19 -04002646 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002647 DeviceId: dh.device.Id,
2648 Port: logicalPortNum,
2649 Packet: packetIn.Pkt,
2650 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302651 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002652 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302653 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002654 "device-id": dh.device.Id,
2655 "packet": hex.EncodeToString(packetIn.Pkt),
2656 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002657 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002658
Matteo Scandolo92186242020-06-12 10:54:18 -07002659 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002660 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002661 "packet": hex.EncodeToString(packetIn.Pkt),
2662 "device-id": dh.device.Id,
2663 })
2664 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002665 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002666}
2667
Mahir Gunyela2e68702022-12-07 00:00:42 -08002668// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2669func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2670 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2671 if err != nil {
2672 return olterrors.NewErrInvalidValue(log.Fields{
2673 "egress-nni-port": egressPortNo,
2674 "device-id": dh.device.Id,
2675 }, err)
2676 }
2677 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2678
2679 if logger.V(log.DebugLevel) {
2680 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2681 "uplink-pkt": uplinkPkt,
2682 "packet": hex.EncodeToString(packet.Data),
2683 "device-id": dh.device.Id,
2684 })
2685 }
2686
2687 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2688 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2689 "packet": hex.EncodeToString(packet.Data),
2690 "device-id": dh.device.Id,
2691 }, err)
2692 }
2693 return nil
2694}
2695
2696// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2697func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2698 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2699 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2700 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2701 // Do not packet-out lldp packets on uni port.
2702 // ONOS has no clue about uni/nni ports, it just packets out on all
2703 // available ports on the Logical Switch. It should not be interested
2704 // in the UNI links.
2705 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2706 "device-id": dh.device.Id,
2707 })
2708 return nil
2709 }
2710 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2711 if innerEthType == 0x8100 {
2712 // q-in-q 802.1ad or 802.1q double tagged packet.
2713 // slice out the outer tag.
2714 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2715 if logger.V(log.DebugLevel) {
2716 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2717 "packet-data": hex.EncodeToString(packet.Data),
2718 "device-id": dh.device.Id,
2719 })
2720 }
2721 }
2722 }
2723 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2724 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2725 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2726 var gemPortID uint32
2727 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2728 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2729 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2730 }
2731 if err != nil {
2732 // In this case the openolt agent will receive the gemPortID as 0.
2733 // The agent tries to retrieve the gemPortID in this case.
2734 // This may not always succeed at the agent and packetOut may fail.
2735 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2736 "intf-id": intfID,
2737 "onu-id": onuID,
2738 "uni-id": uniID,
2739 "packet": hex.EncodeToString(packet.Data),
2740 "device-id": dh.device.Id,
2741 "error": err,
2742 })
2743 }
2744
2745 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2746 if logger.V(log.DebugLevel) {
2747 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2748 "egress-port-no": egressPortNo,
2749 "intf-id": intfID,
2750 "onu-id": onuID,
2751 "uni-id": uniID,
2752 "gem-port-id": gemPortID,
2753 "packet": hex.EncodeToString(packet.Data),
2754 "device-id": dh.device.Id,
2755 })
2756 }
2757
2758 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2759 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2760 "source": "adapter",
2761 "destination": "onu",
2762 "egress-port-number": egressPortNo,
2763 "intf-id": intfID,
2764 "oni-id": onuID,
2765 "uni-id": uniID,
2766 "gem-port-id": gemPortID,
2767 "packet": hex.EncodeToString(packet.Data),
2768 "device-id": dh.device.Id,
2769 }, err)
2770 }
2771 return nil
2772}
2773
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002774// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002775func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002776 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002777 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002778 "device-id": dh.device.Id,
2779 "egress-port-no": egressPortNo,
2780 "pkt-length": len(packet.Data),
2781 "packet": hex.EncodeToString(packet.Data),
2782 })
2783 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002784
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002785 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002786 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002787 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002788 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002789 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002790 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002791 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002792 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302793 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002794 "egressPortType": egressPortType,
2795 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302796 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002797 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002798 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002799 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002800}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002801
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002802func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2803 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002804}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302805
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002806func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002807 defer func() {
2808 dh.lockDevice.Lock()
2809 dh.isHeartbeatCheckActive = false
2810 dh.lockDevice.Unlock()
2811 }()
2812
2813 dh.lockDevice.Lock()
2814 dh.isHeartbeatCheckActive = true
2815 dh.lockDevice.Unlock()
2816
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302817 // start the heartbeat check towards the OLT.
2818 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302819 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302820
2821 for {
2822 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2823 select {
2824 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002825 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002826 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002827 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302828 if timerCheck == nil {
2829 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002830 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302831 }
2832 } else {
2833 if timerCheck != nil {
2834 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002835 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302836 }
2837 timerCheck = nil
2838 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302839 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2840 if dh.heartbeatSignature == 0 {
2841 // First time the signature will be 0, update the signture to DB when not found.
2842 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2843 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2844 }
2845 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2846
2847 dh.lockDevice.RLock()
2848 // Stop the read indication only if it the routine is active
2849 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2850 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2851 // on next execution of the readIndication routine.
2852 if !dh.isReadIndicationRoutineActive {
2853 // Start reading indications
2854 go func() {
2855 if err = dh.readIndications(ctx); err != nil {
2856 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2857 }
2858 }()
2859 }
2860 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302861 } else {
2862 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2863 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2864 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2865 go dh.updateStateRebooted(ctx)
2866 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302867 }
2868 cancel()
2869 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002870 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302871 return
2872 }
2873 }
2874}
2875
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002876func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002877 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002878 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002879 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2880 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2881 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2882 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2883 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002884 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002885 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2886 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002887 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302888
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302889 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002890 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002891 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002892 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002893 DeviceId: dh.device.Id,
2894 OperStatus: voltha.OperStatus_UNKNOWN,
2895 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2896 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002897 _ = 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 -04002898 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302899 /*
2900 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2901 DeviceId: dh.device.Id,
2902 PortTypeFilter: 0,
2903 OperStatus: voltha.OperStatus_UNKNOWN,
2904 }); err != nil {
2905 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2906 }
2907 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002908
Akash Kankanala041a2122024-10-16 15:49:22 +05302909 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002910 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002911 cloned := proto.Clone(device).(*voltha.Device)
2912 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2913 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2914 dh.device = cloned // update local copy of the device
2915 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002916
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002917 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002918 // Stop the Stats collector
2919 if dh.isCollectorActive {
2920 dh.stopCollector <- true
2921 }
2922 // stop the heartbeat check routine
2923 if dh.isHeartbeatCheckActive {
2924 dh.stopHeartbeatCheck <- true
2925 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002926 // Stop the read indication only if it the routine is active
2927 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2928 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2929 // on next execution of the readIndication routine.
2930 if dh.isReadIndicationRoutineActive {
2931 dh.stopIndications <- true
2932 }
2933 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002934 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302935 }
2936}
kesavand39e0aa32020-01-28 20:58:50 -05002937
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302938func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2939 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2940 if err != nil || device == nil {
2941 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2942 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2943 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2944 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2945 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2946 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2947 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2948 return
2949 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302950 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07002951 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302952
2953 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2954 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05302955 // First, stop the read indication and heartbeat check routines to prevent any delay
2956 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302957 dh.lockDevice.RLock()
2958 // Stop the read indication only if it the routine is active
2959 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2960 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2961 // on next execution of the readIndication routine.
2962 if dh.isReadIndicationRoutineActive {
2963 dh.stopIndications <- true
2964 }
2965 dh.lockDevice.RUnlock()
2966
bseenivad1c984b2025-01-09 12:54:44 +05302967 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2968 DeviceId: dh.device.Id,
2969 OperStatus: voltha.OperStatus_REBOOTED,
2970 ConnStatus: voltha.ConnectStatus_REACHABLE,
2971 }); err != nil {
2972 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2973 }
2974
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302975 //raise olt communication failure event
2976 raisedTs := time.Now().Unix()
2977 cloned := proto.Clone(device).(*voltha.Device)
2978 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2979 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2980 dh.device = cloned // update local copy of the device
2981 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2982
Gustavo Silva41af9122022-10-11 11:05:13 -03002983 if err := dh.cleanupDeviceResources(ctx); err != nil {
2984 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
2985 } else {
2986 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2987 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002988
2989 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302990 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002991 if dh.isCollectorActive {
2992 dh.stopCollector <- true
2993 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302994 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002995 if dh.isHeartbeatCheckActive {
2996 dh.stopHeartbeatCheck <- true
2997 }
2998 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302999
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003000 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303001
Akash Kankanala041a2122024-10-16 15:49:22 +05303002 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303003 dh.adapterPreviouslyConnected = false
3004 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303005 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3006 if err != nil || childDevices == nil {
3007 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3008 continue
3009 }
3010 if len(childDevices.Items) == 0 {
3011 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3012 break
3013 } else {
3014 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3015 time.Sleep(5 * time.Second)
3016 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303017 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303018 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003019 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303020 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3021 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303022}
3023
kesavand39e0aa32020-01-28 20:58:50 -05003024// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003025func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3026 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3027 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003028}
3029
3030// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3032 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3033 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003034}
3035
Mahir Gunyela2e68702022-12-07 00:00:42 -08003036// 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 +00003037func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3038 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003039 if port.GetType() == voltha.Port_ETHERNET_NNI {
3040 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003041 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303042 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303043 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003044 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003045 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003046 }
3047 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003048 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003049 ponIntf := &oop.Interface{IntfId: ponID}
3050 var operStatus voltha.OperStatus_Types
3051 if enablePort {
3052 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303053 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003054
3055 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303056 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003057 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003058 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003059 }
3060 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003061 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003063 } else {
3064 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303065 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003066 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303067 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003068 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003069 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003070 }
3071 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003072 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003074 }
khenaidoodc2116e2021-10-19 17:33:19 -04003075 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003076 DeviceId: dh.device.Id,
3077 PortType: voltha.Port_PON_OLT,
3078 PortNo: port.PortNo,
3079 OperStatus: operStatus,
3080 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303081 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303082 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003083 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003084 }
3085 return nil
3086}
3087
Mahir Gunyela2e68702022-12-07 00:00:42 -08003088// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003089func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003090 // Disable the port and update the oper_port_status to core
3091 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003092 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003093 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303095 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303096 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003097 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003098 }
3099 }
3100 }
3101 return nil
3102}
3103
Mahir Gunyela2e68702022-12-07 00:00:42 -08003104// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003105func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3106 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3107 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003108 if port.Type == voltha.Port_ETHERNET_NNI {
3109 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003110 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003111 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003112 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003113 }
3114 }
3115 if port.Type == voltha.Port_PON_OLT {
3116 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003117 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003118 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003119 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003120 }
3121 }
3122 }
3123}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003124
3125// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003126func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003127 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003128 if dh.getDeviceDeletionInProgressFlag() {
3129 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3130 // will reboot, so everything will be reset on the pOLT too.
3131 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3132 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3133 return nil
3134 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303135
3136 if dh.transitionMap.currentDeviceState != deviceStateUp {
3137 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})
3138 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3139 }
3140
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003141 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003142 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003143
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003144 var sn *oop.SerialNumber
3145 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003146 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303147 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003148 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303149 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003150 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003151 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003152
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003153 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303154 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003155 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003156 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3157 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3158 "device-id": dh.device.Id,
3159 "intf-id": intfID,
3160 "onuID": onuID,
3161 "err": err})
3162 } else {
3163 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003164 // Delete flows from device before schedulers and queue
3165 // Clear flowids for gem cache.
3166 removedFlows := []uint64{}
3167 for _, gem := range onuGem.GemPorts {
3168 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3169 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303170 // multiple gem port can have the same flow id
3171 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003172 var alreadyRemoved bool
3173 for _, removedFlowID := range removedFlows {
3174 if removedFlowID == flowID {
3175 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3176 alreadyRemoved = true
3177 break
3178 }
3179 }
3180 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003181 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003182 removedFlows = appendUnique64bit(removedFlows, flowID)
3183 }
3184 }
3185 }
3186 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3187 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003188 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3189 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3190 "device-id": dh.device.Id,
3191 "onu-device": onu,
3192 "err": err})
3193 }
yasin saplibddc2d72022-02-08 13:10:17 +00003194 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003195 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3196 "intf-id": intfID,
3197 "onu-device": onu,
3198 "onu-gem": onuGem,
3199 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303200 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003201 }
3202 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003203 }
yasin saplibddc2d72022-02-08 13:10:17 +00003204 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003205 dh.onus.Delete(onuKey)
3206 dh.discOnus.Delete(onuSn)
3207
3208 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003209 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303210 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303211 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003212 "onu-id": onuID}, err).Log()
3213 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003214
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003215 return nil
3216}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003217func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3218 flow := &oop.Flow{FlowId: flowID}
3219 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3220 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3221 "device-id": dh.device.Id})
3222 } else {
3223 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3224 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3225 "device-id": dh.device.Id,
3226 "err": err})
3227 }
3228 }
3229}
Girish Gowdracefae192020-03-19 18:14:10 -07003230
3231func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003232 for _, field := range flow_utils.GetOfbFields(flow) {
3233 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003234 return field.GetPort()
3235 }
3236 }
3237 return InvalidPort
3238}
3239
3240func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003241 for _, action := range flow_utils.GetActions(flow) {
3242 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003243 if out := action.GetOutput(); out != nil {
3244 return out.GetPort()
3245 }
3246 }
3247 }
3248 return InvalidPort
3249}
3250
Girish Gowdracefae192020-03-19 18:14:10 -07003251func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3252 inPort := getInPortFromFlow(flow)
3253 outPort := getOutPortFromFlow(flow)
3254
3255 if inPort == InvalidPort || outPort == InvalidPort {
3256 return inPort, outPort
3257 }
3258
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003259 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003260 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003261 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003262 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003263 return uniPort, outPort
3264 }
3265 }
3266 } else {
3267 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003268 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003269 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003270 return inPort, uniPort
3271 }
3272 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003273 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003274 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003275 return uniPort, outPort
3276 }
3277 }
3278 }
3279
3280 return InvalidPort, InvalidPort
3281}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003282
3283func extractOmciTransactionID(omciPkt []byte) uint16 {
3284 if len(omciPkt) > 3 {
3285 d := omciPkt[0:2]
3286 transid := binary.BigEndian.Uint16(d)
3287 return transid
3288 }
3289 return 0
3290}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003291
3292// StoreOnuDevice stores the onu parameters to the local cache.
3293func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3294 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3295 dh.onus.Store(onuKey, onuDevice)
3296}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003297
khenaidoodc2116e2021-10-19 17:33:19 -04003298func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003299 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003300 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003301 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003302 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003303 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003304 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003305 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003306 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3307 return nil, err
3308 }
3309 ID = device.ProxyAddress.GetOnuId()
3310 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3311 valueparam.Onu = &Onu
3312 valueparam.Value = value
3313
3314 // This API is unsupported until agent patch is added
3315 resp.Unsupported = uint32(value)
3316 _ = ctx
3317
3318 // Uncomment this code once agent changes are complete and tests
3319 /*
3320 resp, err = dh.Client.GetValue(ctx, valueparam)
3321 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003322 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003323 return nil, err
3324 }
3325 */
3326
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003327 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 -08003328 return resp, nil
3329}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003330
Akash Kankanala041a2122024-10-16 15:49:22 +05303331func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003332 // Default to NNI
3333 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003334 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003335 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003336 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003337 }
3338 return intfID
3339}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003340
Akash Kankanala041a2122024-10-16 15:49:22 +05303341func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003342 dh.perPonOnuIndicationChannelLock.Lock()
3343 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3344 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003345 return ch.indicationChannel
3346 }
3347 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303348 // We create a buffered channel here to avoid calling function to be blocked
3349 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003350 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003351 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003352 stopChannel: make(chan struct{}),
3353 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003354 dh.perPonOnuIndicationChannel[intfID] = channels
3355 dh.perPonOnuIndicationChannelLock.Unlock()
3356 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003357 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003358}
3359
Mahir Gunyelb0046752021-02-26 13:51:05 -08003360func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3361 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3362 dh.perPonOnuIndicationChannelLock.Lock()
3363 defer dh.perPonOnuIndicationChannelLock.Unlock()
3364 for _, v := range dh.perPonOnuIndicationChannel {
3365 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003366 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003367 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003368}
3369
Mahir Gunyelb0046752021-02-26 13:51:05 -08003370func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3371 ind := onuIndicationMsg{
3372 ctx: ctx,
3373 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003374 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003375 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003376 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303377 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003378}
3379
Mahir Gunyelb0046752021-02-26 13:51:05 -08003380func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003381 for {
3382 select {
3383 // process one indication per onu, before proceeding to the next one
3384 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003385 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003386 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003387 "ind": indication})
3388 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003389 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003390 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003391 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3392 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003393 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003394 }
3395 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003396 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003397 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3398 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003399 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003400 }
3401 }
3402 case <-onuChannels.stopChannel:
3403 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3404 close(onuChannels.indicationChannel)
3405 return
3406 }
3407 }
3408}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003409
3410// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3411// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003412func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003413 if dh.getDeviceDeletionInProgressFlag() {
3414 // The device itself is going to be reset as part of deletion. So nothing to be done.
3415 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3416 return nil
3417 }
3418
Girish Gowdra491a9c62021-01-06 16:43:07 -08003419 // Step1 : Fill McastFlowOrGroupControlBlock
3420 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3421 // Step3 : Wait on response channel for response
3422 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003423 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003424 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3425 errChan := make(chan error)
3426 var groupID uint32
3427 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3428 ctx: ctx,
3429 flowOrGroupAction: action,
3430 flow: flow,
3431 group: group,
3432 errChan: &errChan,
3433 }
3434 if flow != nil {
3435 groupID = flow_utils.GetGroup(flow)
3436 } else if group != nil {
3437 groupID = group.Desc.GroupId
3438 } else {
3439 return errors.New("flow-and-group-both-nil")
3440 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003441 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3442 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3443 // Derive the appropriate go routine to handle the request by a simple module operation.
3444 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3445 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3446 // Wait for handler to return error value
3447 err := <-errChan
3448 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3449 return err
3450 }
3451 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3452 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003453}
3454
3455// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003456func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003457 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003458 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003459 // block on the channel to receive an incoming mcast flow/group
3460 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003461 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3462 if mcastFlowOrGroupCb.flow != nil {
3463 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3464 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3465 log.Fields{"device-id": dh.device.Id,
3466 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003467 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3468 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3469 for _, flMgr := range dh.flowMgr {
3470 if flMgr != nil {
3471 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3472 break
3473 }
3474 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003475 // Pass the return value over the return channel
3476 *mcastFlowOrGroupCb.errChan <- err
3477 } else { // flow remove
3478 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3479 log.Fields{"device-id": dh.device.Id,
3480 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003481 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3482 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3483 for _, flMgr := range dh.flowMgr {
3484 if flMgr != nil {
3485 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3486 break
3487 }
3488 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003489 // Pass the return value over the return channel
3490 *mcastFlowOrGroupCb.errChan <- err
3491 }
3492 } else { // mcast group
3493 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3494 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3495 log.Fields{"device-id": dh.device.Id,
3496 "groupToAdd": mcastFlowOrGroupCb.group})
3497 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3498 // Pass the return value over the return channel
3499 *mcastFlowOrGroupCb.errChan <- err
3500 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3501 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3502 log.Fields{"device-id": dh.device.Id,
3503 "groupToModify": mcastFlowOrGroupCb.group})
3504 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3505 // Pass the return value over the return channel
3506 *mcastFlowOrGroupCb.errChan <- err
3507 } else { // group remove
3508 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3509 log.Fields{"device-id": dh.device.Id,
3510 "groupToRemove": mcastFlowOrGroupCb.group})
3511 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3512 // Pass the return value over the return channel
3513 *mcastFlowOrGroupCb.errChan <- err
3514 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003515 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003516 case <-stopHandler:
3517 dh.mcastHandlerRoutineActive[routineIndex] = false
3518 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003519 }
3520 }
3521}
kesavand62126212021-01-12 04:56:06 -05003522
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003523// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003524func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003525 for i, v := range dh.stopMcastHandlerRoutine {
3526 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003527 select {
3528 case v <- true:
3529 case <-time.After(time.Second * 5):
3530 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3531 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003532 }
3533 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003534
3535 if dh.incomingMcastFlowOrGroup != nil {
3536 for k := range dh.incomingMcastFlowOrGroup {
3537 if dh.incomingMcastFlowOrGroup[k] != nil {
3538 dh.incomingMcastFlowOrGroup[k] = nil
3539 }
3540 }
3541 dh.incomingMcastFlowOrGroup = nil
3542 }
3543
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003544 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003545 logger.Debug(ctx, "stopped all mcast handler routines")
3546}
3547
Akash Kankanala041a2122024-10-16 15:49:22 +05303548// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003549func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003550 singleValResp := extension.SingleGetValueResponse{
3551 Response: &extension.GetValueResponse{
3552 Response: &extension.GetValueResponse_PortCoutners{
3553 PortCoutners: &extension.GetOltPortCountersResponse{},
3554 },
3555 },
3556 }
3557
Akash Kankanala041a2122024-10-16 15:49:22 +05303558 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003559 return &extension.SingleGetValueResponse{
3560 Response: &extension.GetValueResponse{
3561 Status: status,
3562 ErrReason: reason,
3563 },
3564 }
3565 }
3566
3567 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3568 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303569 // send error response
kesavand62126212021-01-12 04:56:06 -05003570 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3571 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3572 }
3573 statIndChn := make(chan bool, 1)
3574 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3575 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303576 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003577
3578 go func() {
3579 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3580 if err != nil {
3581 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3582 }
3583 }()
3584 select {
3585 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303586 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003587 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3588 case <-time.After(oltPortInfoTimeout * time.Second):
3589 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3590 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3591 case <-ctx.Done():
3592 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3593 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3594 }
3595 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
Akash Kankanala041a2122024-10-16 15:49:22 +05303596 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003597 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003598 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3599 cmnni := dh.portStats.collectNNIMetrics(intfID)
3600 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303601 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003602 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3603 }
3604 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3605 return &singleValResp
kesavand62126212021-01-12 04:56:06 -05003606 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3607 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003608 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003609 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3610 cmpon := dh.portStats.collectPONMetrics(intfID)
3611 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303612 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003613 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3614 }
3615 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3616 return &singleValResp
3617 }
3618 }
3619 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3620}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303621
Akash Kankanala041a2122024-10-16 15:49:22 +05303622//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303623func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303624 singleValResp := extension.SingleGetValueResponse{
3625 Response: &extension.GetValueResponse{
3626 Status: extension.GetValueResponse_OK,
3627 Response: &extension.GetValueResponse_OffloadedAppsStats{
3628 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3629 },
3630 },
3631 }
3632
3633 return &singleValResp
3634}
3635
Akash Kankanala041a2122024-10-16 15:49:22 +05303636//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303637func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303638 singleValResp := extension.SingleSetValueResponse{
3639 Response: &extension.SetValueResponse{
3640 Status: extension.SetValueResponse_OK,
3641 },
3642 }
3643
3644 return &singleValResp
3645}
3646
Akash Kankanala041a2122024-10-16 15:49:22 +05303647//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303648func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303649 singleValResp := extension.SingleSetValueResponse{
3650 Response: &extension.SetValueResponse{
3651 Status: extension.SetValueResponse_OK,
3652 },
3653 }
3654
3655 return &singleValResp
3656}
3657
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303658func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303659 singleValResp := extension.SingleGetValueResponse{
3660 Response: &extension.GetValueResponse{
3661 Response: &extension.GetValueResponse_OnuPonCounters{
3662 OnuPonCounters: &extension.GetOnuCountersResponse{},
3663 },
3664 },
3665 }
3666
Akash Kankanala041a2122024-10-16 15:49:22 +05303667 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303668 return &extension.SingleGetValueResponse{
3669 Response: &extension.GetValueResponse{
3670 Status: status,
3671 ErrReason: reason,
3672 },
3673 }
3674 }
3675 intfID := onuPonInfo.IntfId
3676 onuID := onuPonInfo.OnuId
3677 onuKey := dh.formOnuKey(intfID, onuID)
3678
3679 if _, ok := dh.onus.Load(onuKey); !ok {
3680 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3681 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3682 }
3683 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3684 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3685 if cmnni == nil {
3686 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3687 }
3688 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3689 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303690}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003691
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303692func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3693 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3694 if err != nil {
3695 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3696 return nil, err
3697 }
3698 if onuGemInfo != nil {
3699 if len(onuGemInfo.UniPorts) == 0 {
3700 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
3701 return nil, err
3702 }
3703 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
3704 return onuGemInfo, nil
3705 }
3706 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
3707 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
3708}
3709
3710func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
3711 var err error
3712 var allocStats *oop.OnuAllocIdStatistics
3713 var onuGemStats *oop.GemPortStatistics
3714 for _, uni := range onuGemInfo.UniPorts {
3715 uniID := plt.UniIDFromPortNum(uni)
3716 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
3717 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
3718 if len(tpIDs) == 0 {
3719 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
3720 continue
3721 }
3722 for _, tpId := range tpIDs {
3723 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
3724 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
3725 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
3726 if techProfileInstance != nil {
3727 switch tpInst := techProfileInstance.(type) {
3728 case *tp_pb.TechProfileInstance:
3729 allocId := tpInst.UsScheduler.AllocId
3730 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
3731 allocStats, err = dh.Client.GetAllocIdStatistics(ctx, &onuAllocPkt)
3732 if err != nil {
3733 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
3734 return err
3735 }
3736 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
3737 allocIdInfo.AllocId = allocStats.AllocId
3738 allocIdInfo.RxBytes = allocStats.RxBytes
3739
3740 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
3741
3742 gemPorts := tpInst.UpstreamGemPortAttributeList
3743 for _, gem := range gemPorts {
3744 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
3745 onuGemStats, err = dh.Client.GetGemPortStatistics(ctx, &onuGemPkt)
3746 if err != nil {
3747 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
3748 return err
3749 }
3750 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
3751 gemStatsInfo.GemId = onuGemStats.GemportId
3752 gemStatsInfo.RxBytes = onuGemStats.RxBytes
3753 gemStatsInfo.RxPackets = onuGemStats.RxPackets
3754 gemStatsInfo.TxBytes = onuGemStats.TxBytes
3755 gemStatsInfo.TxPackets = onuGemStats.TxPackets
3756
3757 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
3758 }
3759 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
3760
3761 default:
3762 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
3763 return err
3764 }
3765 } else {
3766 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
3767 continue
3768 }
3769 }
3770 }
3771 return err
3772}
3773
3774//nolint:unparam
3775func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
3776 singleValResp := extension.SingleGetValueResponse{
3777 Response: &extension.GetValueResponse{
3778 Status: extension.GetValueResponse_OK,
3779 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
3780 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
3781 },
3782 },
3783 }
3784 errResp := func(status extension.GetValueResponse_Status,
3785 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3786 return &extension.SingleGetValueResponse{
3787 Response: &extension.GetValueResponse{
3788 Status: status,
3789 ErrReason: reason,
3790 },
3791 }
3792 }
3793
3794 var intfID, onuID uint32
3795 if onuDevice != nil {
3796 onuID = onuDevice.ProxyAddress.OnuId
3797 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
3798 }
3799
3800 onuKey := dh.formOnuKey(intfID, onuID)
3801 if _, ok := dh.onus.Load(onuKey); !ok {
3802 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
3803 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3804 }
3805 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
3806
3807 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
3808 if err == nil {
3809 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
3810 if err != nil {
3811 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3812 }
3813 } else {
3814 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3815 }
3816 return &singleValResp
3817}
3818
nikesh.krishnanc8473432023-06-14 12:14:54 +05303819func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05303820 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3821 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3822 if err != nil {
3823 return nil, err
3824 }
3825 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05303826}
3827
3828func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05303829 Intf := oop.Interface{IntfId: intfID}
3830 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3831 if err != nil {
3832 return nil, err
3833 }
3834 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05303835}
3836
Gamze Abaka85e9a142021-05-26 13:41:39 +00003837func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00003838 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3839 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3840 if err != nil {
3841 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3842 return generateSingleGetValueErrorResponse(err)
3843 }
3844 return &extension.SingleGetValueResponse{
3845 Response: &extension.GetValueResponse{
3846 Status: extension.GetValueResponse_OK,
3847 Response: &extension.GetValueResponse_RxPower{
3848 RxPower: &extension.GetRxPowerResponse{
3849 IntfId: rxPowerRequest.IntfId,
3850 OnuId: rxPowerRequest.OnuId,
3851 Status: rxPower.Status,
3852 FailReason: rxPower.FailReason.String(),
3853 RxPower: rxPower.RxPowerMeanDbm,
3854 },
3855 },
3856 },
3857 }
3858}
3859
praneeth nalmas55616d62023-02-06 09:19:18 +05303860func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05303861 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05303862 return &extension.SingleGetValueResponse{
3863 Response: &extension.GetValueResponse{
3864 Status: status,
3865 ErrReason: reason,
3866 },
3867 }
3868 }
3869
3870 resp := extension.SingleGetValueResponse{
3871 Response: &extension.GetValueResponse{
3872 Status: extension.GetValueResponse_OK,
3873 Response: &extension.GetValueResponse_OltRxPower{
3874 OltRxPower: &extension.GetOltRxPowerResponse{},
3875 },
3876 },
3877 }
3878
3879 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3880 portLabel := OltRxPowerRequest.PortLabel
3881 serialNumber := OltRxPowerRequest.OnuSn
3882
3883 portInfo := strings.Split(portLabel, "-")
3884 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3885
3886 if err != nil {
3887 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3888 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3889 }
3890
3891 if portInfo[0] != "pon" {
3892 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3893 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3894 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303895
3896 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05303897 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3898 if onuDev != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05303899 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3900 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3901 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05303902 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3903 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05303904 }
3905
3906 rxPowerValue := extension.RxPower{}
3907 rxPowerValue.OnuSn = onuDev.serialNumber
3908 rxPowerValue.Status = rxPower.GetStatus()
3909 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3910 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3911
3912 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05303913 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303914 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3915 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3916 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303917 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303918 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303919 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303920 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05303921 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3922 if err != nil {
3923 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3924 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303925 rxPowerValue := extension.RxPower{}
3926 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3927 rxPowerValue.Status = rxPower.GetStatus()
3928 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3929 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3930
3931 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3932 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303933 }
3934 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3935 return true
3936 })
3937 }
3938 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3939 return &resp
3940}
3941
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05303942func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
3943 errResp := func(status extension.GetValueResponse_Status,
3944 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3945 return &extension.SingleGetValueResponse{
3946 Response: &extension.GetValueResponse{
3947 Status: status,
3948 ErrReason: reason,
3949 },
3950 }
3951 }
3952
3953 resp := extension.SingleGetValueResponse{
3954 Response: &extension.GetValueResponse{
3955 Status: extension.GetValueResponse_OK,
3956 Response: &extension.GetValueResponse_OltPonStatsResponse{
3957 OltPonStatsResponse: &extension.GetPonStatsResponse{},
3958 },
3959 },
3960 }
3961
3962 portLabel := ponStatsRequest.GetPortLabel()
3963 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
3964
3965 portInfo := strings.Split(portLabel, "-")
3966 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3967
3968 if err != nil {
3969 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3970 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3971 }
3972
3973 if portInfo[0] != "pon" {
3974 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
3975 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3976 }
3977
3978 Interface := oop.Interface{IntfId: uint32(portNumber)}
3979 ponStats, err := dh.Client.GetPonPortStatistics(ctx, &Interface)
3980 if err != nil {
3981 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
3982 return generateSingleGetValueErrorResponse(err)
3983 }
3984
3985 ponPortStats := resp.Response.GetOltPonStatsResponse()
3986 ponPortStats.PonPort = uint32(portNumber)
3987 ponPortStats.PortStatistics = ponStats
3988
3989 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
3990 return &resp
3991}
3992
3993func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
3994 errResp := func(status extension.GetValueResponse_Status,
3995 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3996 return &extension.SingleGetValueResponse{
3997 Response: &extension.GetValueResponse{
3998 Status: status,
3999 ErrReason: reason,
4000 },
4001 }
4002 }
4003
4004 resp := extension.SingleGetValueResponse{
4005 Response: &extension.GetValueResponse{
4006 Status: extension.GetValueResponse_OK,
4007 Response: &extension.GetValueResponse_OltNniStatsResponse{
4008 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4009 },
4010 },
4011 }
4012
4013 portLabel := nniStatsRequest.GetPortLabel()
4014 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4015
4016 portInfo := strings.Split(portLabel, "-")
4017 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4018
4019 if err != nil {
4020 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4021 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4022 }
4023
4024 if portInfo[0] != "nni" {
4025 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4026 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4027 }
4028
4029 Interface := oop.Interface{IntfId: uint32(portNumber)}
4030 nniStats, err := dh.Client.GetNniPortStatistics(ctx, &Interface)
4031 if err != nil {
4032 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4033 return generateSingleGetValueErrorResponse(err)
4034 }
4035
4036 nniPortStats := resp.Response.GetOltNniStatsResponse()
4037 nniPortStats.NniPort = uint32(portNumber)
4038 nniPortStats.PortStatistics = nniStats
4039
4040 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4041 return &resp
4042}
4043
Akash Kankanala041a2122024-10-16 15:49:22 +05304044// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004045func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304046 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004047 return &extension.SingleGetValueResponse{
4048 Response: &extension.GetValueResponse{
4049 Status: status,
4050 ErrReason: reason,
4051 },
4052 }
4053 }
4054
4055 if err != nil {
4056 if e, ok := status.FromError(err); ok {
4057 switch e.Code() {
4058 case codes.Internal:
4059 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4060 case codes.DeadlineExceeded:
4061 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4062 case codes.Unimplemented:
4063 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4064 case codes.NotFound:
4065 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4066 }
4067 }
4068 }
4069
4070 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4071}
khenaidoo106c61a2021-08-11 18:05:46 -04004072
4073/*
4074Helper functions to communicate with Core
4075*/
4076
4077func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4078 cClient, err := dh.coreClient.GetCoreServiceClient()
4079 if err != nil || cClient == nil {
4080 return nil, err
4081 }
4082 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4083 defer cancel()
4084 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4085}
4086
khenaidoodc2116e2021-10-19 17:33:19 -04004087func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004088 cClient, err := dh.coreClient.GetCoreServiceClient()
4089 if err != nil || cClient == nil {
4090 return nil, err
4091 }
4092 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4093 defer cancel()
4094 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4095}
4096
khenaidoodc2116e2021-10-19 17:33:19 -04004097func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004098 cClient, err := dh.coreClient.GetCoreServiceClient()
4099 if err != nil || cClient == nil {
4100 return err
4101 }
4102 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4103 defer cancel()
4104 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4105 return err
4106}
4107
4108func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4109 cClient, err := dh.coreClient.GetCoreServiceClient()
4110 if err != nil || cClient == nil {
4111 return nil, err
4112 }
4113 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4114 defer cancel()
4115 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4116}
4117
4118func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4119 cClient, err := dh.coreClient.GetCoreServiceClient()
4120 if err != nil || cClient == nil {
4121 return nil, err
4122 }
4123 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4124 defer cancel()
4125 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4126}
4127
4128func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4129 cClient, err := dh.coreClient.GetCoreServiceClient()
4130 if err != nil || cClient == nil {
4131 return err
4132 }
4133 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4134 defer cancel()
4135 _, err = cClient.DeviceUpdate(subCtx, device)
4136 return err
4137}
4138
khenaidoodc2116e2021-10-19 17:33:19 -04004139func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004140 cClient, err := dh.coreClient.GetCoreServiceClient()
4141 if err != nil || cClient == nil {
4142 return nil, err
4143 }
4144 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4145 defer cancel()
4146 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4147}
4148
khenaidoodc2116e2021-10-19 17:33:19 -04004149func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004150 cClient, err := dh.coreClient.GetCoreServiceClient()
4151 if err != nil || cClient == nil {
4152 return err
4153 }
4154 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4155 defer cancel()
4156 _, err = cClient.SendPacketIn(subCtx, pkt)
4157 return err
4158}
4159
4160func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4161 cClient, err := dh.coreClient.GetCoreServiceClient()
4162 if err != nil || cClient == nil {
4163 return err
4164 }
4165 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4166 defer cancel()
4167 _, err = cClient.PortCreated(subCtx, port)
4168 return err
4169}
4170
khenaidoodc2116e2021-10-19 17:33:19 -04004171func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004172 cClient, err := dh.coreClient.GetCoreServiceClient()
4173 if err != nil || cClient == nil {
4174 return err
4175 }
4176 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4177 defer cancel()
4178 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4179 return err
4180}
4181
khenaidoodc2116e2021-10-19 17:33:19 -04004182func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004183 cClient, err := dh.coreClient.GetCoreServiceClient()
4184 if err != nil || cClient == nil {
4185 return err
4186 }
4187 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4188 defer cancel()
4189 _, err = cClient.PortStateUpdate(subCtx, portState)
4190 return err
4191}
4192
khenaidoodc2116e2021-10-19 17:33:19 -04004193func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004194 cClient, err := dh.coreClient.GetCoreServiceClient()
4195 if err != nil || cClient == nil {
4196 return nil, err
4197 }
4198 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4199 defer cancel()
4200 return cClient.GetDevicePort(subCtx, portFilter)
4201}
4202
nikesh.krishnanc8473432023-06-14 12:14:54 +05304203func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4204 cClient, err := dh.coreClient.GetCoreServiceClient()
4205 if err != nil || cClient == nil {
4206 return nil, err
4207 }
4208 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4209 defer cancel()
4210 return cClient.GetPorts(subCtx, portFilter)
4211}
4212
khenaidoo106c61a2021-08-11 18:05:46 -04004213/*
4214Helper functions to communicate with child adapter
4215*/
4216
khenaidoodc2116e2021-10-19 17:33:19 -04004217func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004218 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4219 if err != nil || aClient == nil {
4220 return err
4221 }
4222 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4223 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4224 defer cancel()
4225 _, err = aClient.OmciIndication(subCtx, response)
4226 return err
4227}
4228
khenaidoodc2116e2021-10-19 17:33:19 -04004229func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004230 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4231 if err != nil || aClient == nil {
4232 return err
4233 }
4234 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4235 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4236 defer cancel()
4237 _, err = aClient.OnuIndication(subCtx, onuInd)
4238 return err
4239}
4240
khenaidoodc2116e2021-10-19 17:33:19 -04004241func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004242 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4243 if err != nil || aClient == nil {
4244 return err
4245 }
4246 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4247 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4248 defer cancel()
4249 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4250 return err
4251}
4252
khenaidoodc2116e2021-10-19 17:33:19 -04004253func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004254 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4255 if err != nil || aClient == nil {
4256 return err
4257 }
4258 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4259 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4260 defer cancel()
4261 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4262 return err
4263}
4264
khenaidoodc2116e2021-10-19 17:33:19 -04004265func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004266 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4267 if err != nil || aClient == nil {
4268 return err
4269 }
4270 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4271 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4272 defer cancel()
4273 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4274 return err
4275}
4276
4277/*
4278Helper functions for remote communication
4279*/
4280
4281// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4282// supports is deleted
4283func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4284 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4285
4286 dh.lockChildAdapterClients.Lock()
4287 defer dh.lockChildAdapterClients.Unlock()
4288 if _, ok := dh.childAdapterClients[endpoint]; ok {
4289 // Already set
4290 return nil
4291 }
4292
4293 // Setup child's adapter grpc connection
4294 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004295 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4296 dh.cfg.AdapterEndpoint,
4297 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004298 "onu_inter_adapter_service.OnuInterAdapterService",
4299 dh.onuInterAdapterRestarted,
4300 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004301 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4302 return err
4303 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304304 retryCodes := []codes.Code{
4305 codes.Unavailable, // server is currently unavailable
4306 codes.DeadlineExceeded, // deadline for the operation was exceeded
4307 }
4308 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4309 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 -04004310
nikesh.krishnand9812542023-08-01 18:31:39 +05304311 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004312 // Wait until we have a connection to the child adapter.
4313 // Unlimited retries or until context expires
4314 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4315 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4316 for {
4317 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4318 if err == nil && client != nil {
4319 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4320 break
4321 }
4322 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4323 // Backoff
4324 if err = backoff.Backoff(subCtx); err != nil {
4325 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4326 break
4327 }
4328 }
4329 return nil
4330}
4331
khenaidoodc2116e2021-10-19 17:33:19 -04004332func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004333 // First check from cache
4334 dh.lockChildAdapterClients.RLock()
4335 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4336 dh.lockChildAdapterClients.RUnlock()
4337 return cgClient.GetOnuInterAdapterServiceClient()
4338 }
4339 dh.lockChildAdapterClients.RUnlock()
4340
4341 // Set the child connection - can occur on restarts
4342 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4343 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4344 cancel()
4345 if err != nil {
4346 return nil, err
4347 }
4348
4349 // Get the child client now
4350 dh.lockChildAdapterClients.RLock()
4351 defer dh.lockChildAdapterClients.RUnlock()
4352 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4353 return cgClient.GetOnuInterAdapterServiceClient()
4354 }
4355 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4356}
4357
4358func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4359 dh.lockChildAdapterClients.Lock()
4360 defer dh.lockChildAdapterClients.Unlock()
4361 for key, client := range dh.childAdapterClients {
4362 client.Stop(ctx)
4363 delete(dh.childAdapterClients, key)
4364 }
4365}
4366
khenaidooefff76e2021-12-15 16:51:30 -05004367// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4368func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4369 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004370 return nil
4371}
4372
khenaidooefff76e2021-12-15 16:51:30 -05004373// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4374func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4375 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004376 return nil
4377 }
khenaidooefff76e2021-12-15 16:51:30 -05004378 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004379}
Girish Gowdra950326e2021-11-05 12:43:24 -07004380
4381func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4382 dh.lockDevice.Lock()
4383 defer dh.lockDevice.Unlock()
4384 dh.isDeviceDeletionInProgress = flag
4385}
4386
4387func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4388 dh.lockDevice.RLock()
4389 defer dh.lockDevice.RUnlock()
4390 return dh.isDeviceDeletionInProgress
4391}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004392
4393// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4394// Returns false if waiting timed out.
4395func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4396 c := make(chan struct{})
4397 go func() {
4398 defer close(c)
4399 wg.Wait()
4400 }()
4401 select {
4402 case <-c:
4403 return true // completed normally
4404 case <-time.After(timeout):
4405 return false // timed out
4406 }
4407}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304408
4409func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4410 val, err := json.Marshal(signature)
4411 if err != nil {
4412 logger.Error(ctx, "failed-to-marshal")
4413 return
4414 }
4415 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4416 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4417 }
4418}
4419
4420func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4421 var signature uint32
4422
4423 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4424 if er == nil {
4425 if Value != nil {
4426 Val, er := kvstore.ToByte(Value.Value)
4427 if er != nil {
4428 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4429 return signature
4430 }
4431 if er = json.Unmarshal(Val, &signature); er != nil {
4432 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4433 return signature
4434 }
4435 }
4436 }
4437 return signature
4438}