blob: 2c18980619ba0e64b4d223416c0bb8a4a4122ae6 [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
1713func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001714 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001715 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301716 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001717
Akash Kankanala041a2122024-10-16 15:49:22 +05301718 // 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 +05301719 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1720 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1721 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1722 if onuDev != nil {
1723 var onuGemInfo *rsrcMgr.OnuGemInfo
1724 var err error
1725 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1726 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1727 return false, err
1728 }
1729 if onuGemInfo != nil {
1730 for _, uni := range onuGemInfo.UniPorts {
1731 uniID := plt.UniIDFromPortNum(uni)
1732 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1733 if len(tpIDs) != 0 {
1734 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1735 tpInstExists = true
1736 break
1737 }
1738 }
1739 }
1740 }
1741 return tpInstExists, nil
1742 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301743
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301744 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1745 ParentId: dh.device.Id,
1746 SerialNumber: sn,
1747 ParentPortNo: parentPortNo,
1748 })
1749 if onuDevice != nil {
1750 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1751 return true, nil
1752 }
1753 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1754
1755 return false, nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301756}
1757
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001758// processDiscONULOSClear clears the LOS Alarm if it's needed
1759func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301760 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001761 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301762
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001763 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1764 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1765 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1766 OnuLosRaise event sent for it */
1767 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1768 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1769 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1770 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1771 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1772 "currentIntfId": onuDiscInd.GetIntfId()})
1773 // TODO:: Should we need to ignore raising OnuLosClear event
1774 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301775 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001776 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1777 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1778 alarmInd.LosStatus = statusCheckOff
1779 go func() {
1780 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1781 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1782 }
1783 }()
1784 // stop iterating
1785 return false
1786 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301787 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001788 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301789}
1790
1791func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301792 var error error
1793
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301794 channelID := onuDiscInd.GetIntfId()
1795 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1796
1797 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301798 defer func() {
1799 if error != nil {
1800 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1801 } else {
1802 // once the function completes set the value to false so that
1803 // we know the processing has inProcess.
1804 // Note that this is done after checking if we are already processing
1805 // to avoid changing the value from a different thread
1806 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1807 dh.discOnus.Store(sn, false)
1808 }
1809 }()
1810
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301811 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1812
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301813 tpInstExists, error := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1814 if error != nil {
1815 return error
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301816 }
1817 if tpInstExists {
Akash Kankanala041a2122024-10-16 15:49:22 +05301818 // ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001819 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001820 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001821 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001822 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1823
1824 // if the ONU existed, handle the LOS Alarm
1825 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001826 if inProcess.(bool) {
1827 // if we're currently processing the ONU on a different thread, do nothing
1828 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1829 return nil
1830 }
1831 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1832 // then continue processing it
1833 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1834
1835 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001836 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301837 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001838 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001839
1840 // check the ONU is already know to the OLT
1841 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301842 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001843 ParentId: dh.device.Id,
1844 SerialNumber: sn,
1845 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001846
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301847 if error != nil {
1848 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1849 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001850 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 -08001851 switch e.Code() {
1852 case codes.Internal:
1853 // this probably means NOT FOUND, so just create a new device
1854 onuDevice = nil
1855 case codes.DeadlineExceeded:
1856 // if the call times out, cleanup and exit
1857 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301858 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1859 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001860 }
1861 }
1862 }
1863
1864 if onuDevice == nil {
1865 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001866 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001867 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001868 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301869 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001870 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001871
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301872 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001873 // if we can't create an ID in resource manager,
1874 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001875 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301876
1877 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001878 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301879 "serial-number": sn}, error)
1880 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001881 }
1882
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301883 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001884 ParentId: dh.device.Id,
1885 ParentPortNo: parentPortNo,
1886 ChannelId: channelID,
1887 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1888 SerialNumber: sn,
1889 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301890 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001891 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001892 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 +05301893
1894 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001895 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301896 "serial-number": sn}, error)
1897 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001898 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301899 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 +05301900 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
1901 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
1902 "onu-id": onuID,
1903 "device-id": dh.device.Id,
1904 "serial-number": sn}, error)
1905 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04001906 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001907 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301908 log.Fields{"onuDevice": onuDevice,
1909 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001910 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301911 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001912 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001913
khenaidoo106c61a2021-08-11 18:05:46 -04001914 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1915 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301916 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04001917 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301918 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301919 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
1920 return error
khenaidoo106c61a2021-08-11 18:05:46 -04001921 }
1922
Matteo Scandolo945e4012019-12-12 14:16:11 -08001923 // we can now use the existing ONU Id
1924 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05301925 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07001926 //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 +00001927 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001928 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301929 "intfId": onuDiscInd.GetIntfId(),
1930 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001931 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001932
khenaidoo106c61a2021-08-11 18:05:46 -04001933 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301934 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001935 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301936 log.Fields{"onu": onuDev,
1937 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001938
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301939 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001940 DeviceId: onuDevice.Id,
1941 ParentDeviceId: dh.device.Id,
1942 OperStatus: common.OperStatus_DISCOVERED,
1943 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301944 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301945 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001946 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301947 "serial-number": sn}, error)
1948 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07001949 }
khenaidoo106c61a2021-08-11 18:05:46 -04001950
Neha Sharma96b7bf22020-06-15 10:37:32 +00001951 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301952 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301953 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001954 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301955 "serial-number": sn}, error)
1956 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08001957 }
1958 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001959}
1960
Mahir Gunyelb0046752021-02-26 13:51:05 -08001961func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001962 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001963 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001964 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001965 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001966 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301967 log.Fields{"onuId": onuInd.OnuId,
1968 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301969 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001970 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001971 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001972 errFields := log.Fields{"device-id": dh.device.Id}
1973
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301974 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05301975 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07001976 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001977 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001978 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001979 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301980 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07001981 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001982 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001983 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001984 errFields["onu-id"] = onuInd.OnuId
1985 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001986 }
khenaidoodc2116e2021-10-19 17:33:19 -04001987 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001988 ParentId: dh.device.Id,
1989 SerialNumber: serialNumber,
1990 OnuId: onuInd.OnuId,
1991 ParentPortNo: ponPort,
1992 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001993 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001994
David K. Bainbridge794735f2020-02-11 21:01:37 -08001995 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001996 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001997 }
1998
David K. Bainbridge794735f2020-02-11 21:01:37 -08001999 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002000 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002001 "previousIntfId": onuDevice.ParentPortNo,
2002 "currentIntfId": ponPort})
2003 }
2004
2005 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002006 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302007 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2008 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302009 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002010 }
2011 if !foundInCache {
2012 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002013 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 -08002014 }
kesavand7cf3a052020-08-28 12:49:18 +05302015 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002016 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002017 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302018 }
2019 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002020 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002021 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002022 }
2023 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002024}
2025
Neha Sharma96b7bf22020-06-15 10:37:32 +00002026func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002027 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 -07002028 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2029 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2030 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2031 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002032 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002033 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2034 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002035 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002036 onuInd.OperState = "down"
2037 }
2038 }
2039
David K. Bainbridge794735f2020-02-11 21:01:37 -08002040 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002041 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002042 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 -04002043
khenaidoodc2116e2021-10-19 17:33:19 -04002044 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002045 DeviceId: onuDevice.Id,
2046 OnuIndication: onuInd,
2047 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002048 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302049 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002050 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002051 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002052 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002053 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002054 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002055 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002056 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002057 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002058 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002059}
2060
cuilin20187b2a8c32019-03-26 19:52:28 -07002061func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2062 if serialNum != nil {
2063 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002064 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002065 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002066}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002067func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2068 decodedStr, err := hex.DecodeString(serialNum[4:])
2069 if err != nil {
2070 return nil, err
2071 }
2072 return &oop.SerialNumber{
2073 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002074 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002075 }, nil
2076}
cuilin20187b2a8c32019-03-26 19:52:28 -07002077
2078func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002079 if len(vendorSpecific) > 3 {
2080 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2081 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2082 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2083 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2084 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2085 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2086 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2087 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2088 return tmp
2089 }
2090 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002091}
2092
Mahir Gunyela2e68702022-12-07 00:00:42 -08002093// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002094func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302095 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002096}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002097
Mahir Gunyela2e68702022-12-07 00:00:42 -08002098// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002099func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2100 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302101 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002102 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302103 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002104
khenaidoodc2116e2021-10-19 17:33:19 -04002105 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002106 ParentId: dh.device.Id,
2107 OnuId: onuID,
2108 ParentPortNo: parentPort,
2109 })
2110
Girish Gowdru0c588b22019-04-23 23:24:56 -04002111 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002112 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002113 "intf-id": parentPort,
2114 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002115 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002116 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 -08002117 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302118}
2119
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002120// SendPacketInToCore sends packet-in to core
2121// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2122// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002123func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002124 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002126 "port": logicalPort,
2127 "packet": hex.EncodeToString(packetPayload),
2128 "device-id": dh.device.Id,
2129 })
2130 }
khenaidoo106c61a2021-08-11 18:05:46 -04002131
khenaidoodc2116e2021-10-19 17:33:19 -04002132 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002133 DeviceId: dh.device.Id,
2134 Port: logicalPort,
2135 Packet: packetPayload,
2136 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302137 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002138 "source": "adapter",
2139 "destination": "core",
2140 "device-id": dh.device.Id,
2141 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002142 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002143 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002144 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002145 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002146 "packet": hex.EncodeToString(packetPayload),
2147 "device-id": dh.device.Id,
2148 })
2149 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002150 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002151}
2152
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002153// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002154func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002155 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002156
2157 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2158 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002159 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002160 }
2161
Kent Hagermane6ff1012020-07-14 15:07:53 -04002162 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002163 metrics := dh.metrics.GetSubscriberMetrics()
2164 for _, m := range pmConfigs.Metrics {
2165 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002166 }
2167 }
2168}
2169
khenaidoodc2116e2021-10-19 17:33:19 -04002170func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002171 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002172 var errorsList []error
2173
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002174 if dh.getDeviceDeletionInProgressFlag() {
2175 // The device itself is going to be reset as part of deletion. So nothing to be done.
2176 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2177 return nil
2178 }
2179
Girish Gowdru0c588b22019-04-23 23:24:56 -04002180 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002181 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302182 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002183
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302185 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002186 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302187 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002188 if flow_utils.HasGroup(flow) {
2189 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2190 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002191 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2192 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2193 } else {
2194 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2195 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002196 }
Girish Gowdracefae192020-03-19 18:14:10 -07002197 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002198 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302199 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002200 logger.Warnw(ctx, "flow-to-remove-not-found",
2201 log.Fields{
2202 "ponIf": intfID,
2203 "flowToRemove": flow,
2204 "error": err,
2205 })
2206 } else {
2207 errorsList = append(errorsList, err)
2208 }
Girish Gowdracefae192020-03-19 18:14:10 -07002209 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002210 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302211
2212 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302213 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002214 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302215 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002216 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302217 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002218 if flow_utils.HasGroup(flow) {
2219 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2220 } else {
yasin saplid0566272021-12-21 09:10:30 +00002221 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002222 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2223 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2224 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2225 } else {
yasin saplid0566272021-12-21 09:10:30 +00002226 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002227 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002228 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002229 if err != nil {
2230 errorsList = append(errorsList, err)
2231 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302232 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002233 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002234
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002235 return errorsList
2236}
2237
2238func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2239 var err error
2240 var errorsList []error
2241
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002242 if dh.getDeviceDeletionInProgressFlag() {
2243 // The device itself is going to be reset as part of deletion. So nothing to be done.
2244 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2245 return nil
2246 }
2247
Girish Gowdracefae192020-03-19 18:14:10 -07002248 // 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 +00002249 if groups != nil {
2250 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002251 // err = dh.groupMgr.AddGroup(ctx, group)
2252 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002253 if err != nil {
2254 errorsList = append(errorsList, err)
2255 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002256 }
2257 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002258 // err = dh.groupMgr.ModifyGroup(ctx, group)
2259 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002260 if err != nil {
2261 errorsList = append(errorsList, err)
2262 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002263 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002264 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002265 // err = dh.groupMgr.DeleteGroup(ctx, group)
2266 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002267 if err != nil {
2268 errorsList = append(errorsList, err)
2269 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002270 }
2271 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002272
2273 return errorsList
2274}
2275
Mahir Gunyela2e68702022-12-07 00:00:42 -08002276// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002277func (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 -07002278 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002279
2280 if dh.getDeviceDeletionInProgressFlag() {
2281 // The device itself is going to be reset as part of deletion. So nothing to be done.
2282 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2283 return nil
2284 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302285 if dh.transitionMap.currentDeviceState != deviceStateUp {
2286 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2287 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2288 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002289 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2290 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2291 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002292 if len(errorsList) > 0 {
2293 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2294 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002295 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002296 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302297}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002298
Mahir Gunyela2e68702022-12-07 00:00:42 -08002299// DisableDevice disables the given device
2300// It marks the following for the given device:
2301// Device-Handler Admin-State : down
2302// Device Port-State: UNKNOWN
2303// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002304func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002305 /* On device disable ,admin state update has to be done prior sending request to agent since
2306 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002307 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002308 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002309 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002310 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002311 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002312 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002313 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002314 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002315 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002316 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302317
2318 dh.discOnus = sync.Map{}
2319 dh.onus = sync.Map{}
2320
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002321 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302322 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002323 if dh.isCollectorActive {
2324 dh.stopCollector <- true
2325 }
2326 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302327
Neha Sharma96b7bf22020-06-15 10:37:32 +00002328 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002329 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302330 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302331 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002332
kdarapu1afeceb2020-02-12 01:38:09 -05002333 // 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 -04002334 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002335 DeviceId: cloned.Id,
2336 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2337 OperStatus: voltha.OperStatus_UNKNOWN,
2338 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002339 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002340 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002341 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002342 return nil
2343}
2344
Neha Sharma96b7bf22020-06-15 10:37:32 +00002345func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002346 // Update onu state as unreachable in onu adapter
2347 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302348 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002349
Akash Kankanala041a2122024-10-16 15:49:22 +05302350 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002351 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002352 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002353 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 -04002354 }
2355 if onuDevices != nil {
2356 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002357 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002358 DeviceId: onuDevice.Id,
2359 OnuIndication: &onuInd,
2360 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002361 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002362 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002363 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002364 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002365 }
2366 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002367}
2368
Mahir Gunyela2e68702022-12-07 00:00:42 -08002369// ReenableDevice re-enables the olt device after disable
2370// It marks the following for the given device:
2371// Device-Handler Admin-State : up
2372// Device Port-State: ACTIVE
2373// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002374func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302375 if dh.Client != nil {
2376 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2377 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2378 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2379 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302380 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302381 } else {
2382 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 +05302383 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002385
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002386 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002387 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002388 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002389 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002390 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2391 } else {
2392 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2393 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2394 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002395 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002396 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302397 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002398 device.OperStatus = voltha.OperStatus_ACTIVE
2399 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302400 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002401 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002402 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002403 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002404
khenaidoodc2116e2021-10-19 17:33:19 -04002405 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002406 DeviceId: device.Id,
2407 OperStatus: device.OperStatus,
2408 ConnStatus: device.ConnectStatus,
2409 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302410 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002411 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002412 "connect-status": device.ConnectStatus,
2413 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002414 }
kesavand39e0aa32020-01-28 20:58:50 -05002415
Neha Sharma96b7bf22020-06-15 10:37:32 +00002416 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002417
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002418 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002419}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002420
npujarec5762e2020-01-01 14:08:48 +05302421func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002422 var uniID uint32
2423 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002424 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302425 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002426 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002427 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002428 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002429 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2430 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2431 } else {
2432 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2433 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002434 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002435 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002436 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002437 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002438 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002439 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002440 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002441 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002442 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002443 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002444 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002445 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002446 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002447 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002448 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002449 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302450 }
yasin saplibddc2d72022-02-08 13:10:17 +00002451 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2452 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002453 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002454 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302455 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002456 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002457 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002458 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 -03002459 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002460 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002461 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002462 if len(errs) > 0 {
2463 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2464 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2465 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002466 return nil
2467}
2468
Devmalya Paul495b94a2019-08-27 19:42:00 -04002469// 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 +05302470func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002471 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002472 /* Clear the KV store data associated with the all the UNI ports
2473 This clears up flow data and also resource map data for various
2474 other pon resources like alloc_id and gemport_id
2475 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002476
2477 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002478 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002479
Himani Chawla49a5d562020-11-25 11:53:44 +05302480 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002481 // Stop the Stats collector
2482 if dh.isCollectorActive {
2483 dh.stopCollector <- true
2484 }
2485 // stop the heartbeat check routine
2486 if dh.isHeartbeatCheckActive {
2487 dh.stopHeartbeatCheck <- true
2488 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302489 // Stop the read indication only if it the routine is active
2490 if dh.isReadIndicationRoutineActive {
2491 dh.stopIndications <- true
2492 }
2493 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302494
2495 err := dh.cleanupDeviceResources(ctx)
2496 if err != nil {
2497 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2498 } else {
2499 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2500 }
2501
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002502 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302503 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002504 if dh.Client != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302505 if _, err = dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002506 go func() {
2507 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302508 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2509 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002510 }
2511 }()
2512 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002513 }
2514 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002515 // There is no need to update the core about operation status and connection status of the OLT.
2516 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2517 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2518 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002519
khenaidoo7eb2d672021-10-22 19:08:50 -04002520 // Stop the adapter grpc clients for that parent device
2521 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002522 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002523}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002524
2525// StopAllFlowRoutines stops all flow routines
2526func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2527 var wg sync.WaitGroup
2528 wg.Add(1) // for the mcast routine below to finish
2529 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2530 for _, flMgr := range dh.flowMgr {
2531 if flMgr != nil {
2532 wg.Add(1) // for the flow handler routine below to finish
2533 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2534 }
2535 }
2536 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2537 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2538 } else {
2539 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2540 }
2541}
2542
Gustavo Silva41af9122022-10-11 11:05:13 -03002543func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2544 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002545 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302546 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002547 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002548 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002549 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002550 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002551 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2552 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302553 }
2554 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002555 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2556 errs = append(errs, err)
2557 }
2558 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2559 errs = append(errs, err)
2560 }
2561 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2562 errs = append(errs, err)
2563 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002564 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002565 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002566 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002567 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002568 }
2569 // Clean up NNI manager's data
2570 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2571 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002572 }
A R Karthick1f85b802019-10-11 05:06:05 +00002573
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002574 dh.CloseKVClient(ctx)
2575
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002576 // Take one final sweep at cleaning up KV store for the OLT device
2577 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002578 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2579 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002580 }
2581
Devmalya Paul495b94a2019-08-27 19:42:00 -04002582 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302583 dh.onus.Range(func(key interface{}, value interface{}) bool {
2584 dh.onus.Delete(key)
2585 return true
2586 })
2587
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002588 /*Delete discovered ONU map for the device*/
2589 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2590 dh.discOnus.Delete(key)
2591 return true
2592 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002593 if len(errs) > 0 {
2594 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2595 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2596 }
2597 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002598}
2599
Mahir Gunyela2e68702022-12-07 00:00:42 -08002600// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002601func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302602 if dh.Client != nil {
2603 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2604 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2605 }
2606 } else {
2607 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 -04002608 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302609
Neha Sharma96b7bf22020-06-15 10:37:32 +00002610 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002611 return nil
2612}
2613
David K. Bainbridge794735f2020-02-11 21:01:37 -08002614func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002615 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002616 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002617 "packet-indication": *packetIn,
2618 "device-id": dh.device.Id,
2619 "packet": hex.EncodeToString(packetIn.Pkt),
2620 })
2621 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002622 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2623 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2624 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002625 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002626 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002627 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002628 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002629 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002630 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002631 "logical-port-num": logicalPortNum,
2632 "device-id": dh.device.Id,
2633 "packet": hex.EncodeToString(packetIn.Pkt),
2634 })
2635 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002636
khenaidoodc2116e2021-10-19 17:33:19 -04002637 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002638 DeviceId: dh.device.Id,
2639 Port: logicalPortNum,
2640 Packet: packetIn.Pkt,
2641 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302642 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002643 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302644 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002645 "device-id": dh.device.Id,
2646 "packet": hex.EncodeToString(packetIn.Pkt),
2647 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002648 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002649
Matteo Scandolo92186242020-06-12 10:54:18 -07002650 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002651 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002652 "packet": hex.EncodeToString(packetIn.Pkt),
2653 "device-id": dh.device.Id,
2654 })
2655 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002656 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002657}
2658
Mahir Gunyela2e68702022-12-07 00:00:42 -08002659// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2660func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2661 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2662 if err != nil {
2663 return olterrors.NewErrInvalidValue(log.Fields{
2664 "egress-nni-port": egressPortNo,
2665 "device-id": dh.device.Id,
2666 }, err)
2667 }
2668 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2669
2670 if logger.V(log.DebugLevel) {
2671 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2672 "uplink-pkt": uplinkPkt,
2673 "packet": hex.EncodeToString(packet.Data),
2674 "device-id": dh.device.Id,
2675 })
2676 }
2677
2678 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2679 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2680 "packet": hex.EncodeToString(packet.Data),
2681 "device-id": dh.device.Id,
2682 }, err)
2683 }
2684 return nil
2685}
2686
2687// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2688func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2689 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2690 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2691 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2692 // Do not packet-out lldp packets on uni port.
2693 // ONOS has no clue about uni/nni ports, it just packets out on all
2694 // available ports on the Logical Switch. It should not be interested
2695 // in the UNI links.
2696 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2697 "device-id": dh.device.Id,
2698 })
2699 return nil
2700 }
2701 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2702 if innerEthType == 0x8100 {
2703 // q-in-q 802.1ad or 802.1q double tagged packet.
2704 // slice out the outer tag.
2705 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2706 if logger.V(log.DebugLevel) {
2707 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2708 "packet-data": hex.EncodeToString(packet.Data),
2709 "device-id": dh.device.Id,
2710 })
2711 }
2712 }
2713 }
2714 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2715 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2716 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2717 var gemPortID uint32
2718 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2719 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2720 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2721 }
2722 if err != nil {
2723 // In this case the openolt agent will receive the gemPortID as 0.
2724 // The agent tries to retrieve the gemPortID in this case.
2725 // This may not always succeed at the agent and packetOut may fail.
2726 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2727 "intf-id": intfID,
2728 "onu-id": onuID,
2729 "uni-id": uniID,
2730 "packet": hex.EncodeToString(packet.Data),
2731 "device-id": dh.device.Id,
2732 "error": err,
2733 })
2734 }
2735
2736 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2737 if logger.V(log.DebugLevel) {
2738 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2739 "egress-port-no": egressPortNo,
2740 "intf-id": intfID,
2741 "onu-id": onuID,
2742 "uni-id": uniID,
2743 "gem-port-id": gemPortID,
2744 "packet": hex.EncodeToString(packet.Data),
2745 "device-id": dh.device.Id,
2746 })
2747 }
2748
2749 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2750 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2751 "source": "adapter",
2752 "destination": "onu",
2753 "egress-port-number": egressPortNo,
2754 "intf-id": intfID,
2755 "oni-id": onuID,
2756 "uni-id": uniID,
2757 "gem-port-id": gemPortID,
2758 "packet": hex.EncodeToString(packet.Data),
2759 "device-id": dh.device.Id,
2760 }, err)
2761 }
2762 return nil
2763}
2764
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002765// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002766func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002767 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002768 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002769 "device-id": dh.device.Id,
2770 "egress-port-no": egressPortNo,
2771 "pkt-length": len(packet.Data),
2772 "packet": hex.EncodeToString(packet.Data),
2773 })
2774 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002775
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002776 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002777 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002778 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002779 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002780 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002781 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002782 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002783 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302784 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002785 "egressPortType": egressPortType,
2786 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302787 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002788 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002789 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002790 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002791}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002792
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002793func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2794 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002795}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302796
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002797func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002798 defer func() {
2799 dh.lockDevice.Lock()
2800 dh.isHeartbeatCheckActive = false
2801 dh.lockDevice.Unlock()
2802 }()
2803
2804 dh.lockDevice.Lock()
2805 dh.isHeartbeatCheckActive = true
2806 dh.lockDevice.Unlock()
2807
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302808 // start the heartbeat check towards the OLT.
2809 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302810 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302811
2812 for {
2813 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2814 select {
2815 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002816 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002817 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002818 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302819 if timerCheck == nil {
2820 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002821 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302822 }
2823 } else {
2824 if timerCheck != nil {
2825 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002826 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302827 }
2828 timerCheck = nil
2829 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302830 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2831 if dh.heartbeatSignature == 0 {
2832 // First time the signature will be 0, update the signture to DB when not found.
2833 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2834 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2835 }
2836 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2837
2838 dh.lockDevice.RLock()
2839 // Stop the read indication only if it the routine is active
2840 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2841 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2842 // on next execution of the readIndication routine.
2843 if !dh.isReadIndicationRoutineActive {
2844 // Start reading indications
2845 go func() {
2846 if err = dh.readIndications(ctx); err != nil {
2847 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2848 }
2849 }()
2850 }
2851 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302852 } else {
2853 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2854 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2855 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2856 go dh.updateStateRebooted(ctx)
2857 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302858 }
2859 cancel()
2860 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002861 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302862 return
2863 }
2864 }
2865}
2866
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002867func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002868 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002869 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002870 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2871 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2872 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2873 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2874 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002875 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002876 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2877 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002878 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302879
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302880 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002881 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002882 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002883 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002884 DeviceId: dh.device.Id,
2885 OperStatus: voltha.OperStatus_UNKNOWN,
2886 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2887 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002888 _ = 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 -04002889 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302890 /*
2891 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2892 DeviceId: dh.device.Id,
2893 PortTypeFilter: 0,
2894 OperStatus: voltha.OperStatus_UNKNOWN,
2895 }); err != nil {
2896 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2897 }
2898 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002899
Akash Kankanala041a2122024-10-16 15:49:22 +05302900 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002901 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002902 cloned := proto.Clone(device).(*voltha.Device)
2903 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2904 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2905 dh.device = cloned // update local copy of the device
2906 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002907
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002908 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002909 // Stop the Stats collector
2910 if dh.isCollectorActive {
2911 dh.stopCollector <- true
2912 }
2913 // stop the heartbeat check routine
2914 if dh.isHeartbeatCheckActive {
2915 dh.stopHeartbeatCheck <- true
2916 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002917 // Stop the read indication only if it the routine is active
2918 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2919 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2920 // on next execution of the readIndication routine.
2921 if dh.isReadIndicationRoutineActive {
2922 dh.stopIndications <- true
2923 }
2924 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002925 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302926 }
2927}
kesavand39e0aa32020-01-28 20:58:50 -05002928
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302929func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2930 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2931 if err != nil || device == nil {
2932 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2933 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2934 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2935 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2936 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2937 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2938 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2939 return
2940 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302941 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07002942 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302943
2944 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2945 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05302946 // First, stop the read indication and heartbeat check routines to prevent any delay
2947 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302948 dh.lockDevice.RLock()
2949 // Stop the read indication only if it the routine is active
2950 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2951 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2952 // on next execution of the readIndication routine.
2953 if dh.isReadIndicationRoutineActive {
2954 dh.stopIndications <- true
2955 }
2956 dh.lockDevice.RUnlock()
2957
bseenivad1c984b2025-01-09 12:54:44 +05302958 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2959 DeviceId: dh.device.Id,
2960 OperStatus: voltha.OperStatus_REBOOTED,
2961 ConnStatus: voltha.ConnectStatus_REACHABLE,
2962 }); err != nil {
2963 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2964 }
2965
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302966 //raise olt communication failure event
2967 raisedTs := time.Now().Unix()
2968 cloned := proto.Clone(device).(*voltha.Device)
2969 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2970 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2971 dh.device = cloned // update local copy of the device
2972 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2973
Gustavo Silva41af9122022-10-11 11:05:13 -03002974 if err := dh.cleanupDeviceResources(ctx); err != nil {
2975 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
2976 } else {
2977 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2978 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002979
2980 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302981 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002982 if dh.isCollectorActive {
2983 dh.stopCollector <- true
2984 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302985 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002986 if dh.isHeartbeatCheckActive {
2987 dh.stopHeartbeatCheck <- true
2988 }
2989 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302990
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002991 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302992
Akash Kankanala041a2122024-10-16 15:49:22 +05302993 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302994 dh.adapterPreviouslyConnected = false
2995 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302996 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2997 if err != nil || childDevices == nil {
2998 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2999 continue
3000 }
3001 if len(childDevices.Items) == 0 {
3002 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3003 break
3004 } else {
3005 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3006 time.Sleep(5 * time.Second)
3007 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303008 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303009 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003010 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303011 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3012 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303013}
3014
kesavand39e0aa32020-01-28 20:58:50 -05003015// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003016func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3017 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3018 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003019}
3020
3021// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003022func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3023 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3024 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003025}
3026
Mahir Gunyela2e68702022-12-07 00:00:42 -08003027// 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 +00003028func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3029 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003030 if port.GetType() == voltha.Port_ETHERNET_NNI {
3031 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003032 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303033 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303034 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003035 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003036 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003037 }
3038 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003039 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003040 ponIntf := &oop.Interface{IntfId: ponID}
3041 var operStatus voltha.OperStatus_Types
3042 if enablePort {
3043 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303044 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003045
3046 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303047 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003048 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003049 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003050 }
3051 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003052 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003053 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003054 } else {
3055 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303056 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003057 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303058 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003059 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003060 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003061 }
3062 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003063 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003064 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003065 }
khenaidoodc2116e2021-10-19 17:33:19 -04003066 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003067 DeviceId: dh.device.Id,
3068 PortType: voltha.Port_PON_OLT,
3069 PortNo: port.PortNo,
3070 OperStatus: operStatus,
3071 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303072 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303073 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003074 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003075 }
3076 return nil
3077}
3078
Mahir Gunyela2e68702022-12-07 00:00:42 -08003079// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003080func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003081 // Disable the port and update the oper_port_status to core
3082 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003083 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003084 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003085 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303086 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303087 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003088 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003089 }
3090 }
3091 }
3092 return nil
3093}
3094
Mahir Gunyela2e68702022-12-07 00:00:42 -08003095// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003096func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3097 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3098 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003099 if port.Type == voltha.Port_ETHERNET_NNI {
3100 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003101 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003102 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003103 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003104 }
3105 }
3106 if port.Type == voltha.Port_PON_OLT {
3107 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003108 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003109 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003110 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003111 }
3112 }
3113 }
3114}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003115
3116// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003117func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003118 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003119 if dh.getDeviceDeletionInProgressFlag() {
3120 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3121 // will reboot, so everything will be reset on the pOLT too.
3122 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3123 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3124 return nil
3125 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303126
3127 if dh.transitionMap.currentDeviceState != deviceStateUp {
3128 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})
3129 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3130 }
3131
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003132 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003133 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003134
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003135 var sn *oop.SerialNumber
3136 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003137 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303138 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003139 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303140 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003141 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003142 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003143
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003144 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303145 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003146 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003147 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3148 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3149 "device-id": dh.device.Id,
3150 "intf-id": intfID,
3151 "onuID": onuID,
3152 "err": err})
3153 } else {
3154 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003155 // Delete flows from device before schedulers and queue
3156 // Clear flowids for gem cache.
3157 removedFlows := []uint64{}
3158 for _, gem := range onuGem.GemPorts {
3159 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3160 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303161 // multiple gem port can have the same flow id
3162 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003163 var alreadyRemoved bool
3164 for _, removedFlowID := range removedFlows {
3165 if removedFlowID == flowID {
3166 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3167 alreadyRemoved = true
3168 break
3169 }
3170 }
3171 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003172 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003173 removedFlows = appendUnique64bit(removedFlows, flowID)
3174 }
3175 }
3176 }
3177 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3178 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003179 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3180 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3181 "device-id": dh.device.Id,
3182 "onu-device": onu,
3183 "err": err})
3184 }
yasin saplibddc2d72022-02-08 13:10:17 +00003185 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003186 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3187 "intf-id": intfID,
3188 "onu-device": onu,
3189 "onu-gem": onuGem,
3190 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303191 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003192 }
3193 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003194 }
yasin saplibddc2d72022-02-08 13:10:17 +00003195 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003196 dh.onus.Delete(onuKey)
3197 dh.discOnus.Delete(onuSn)
3198
3199 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003200 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303201 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303202 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003203 "onu-id": onuID}, err).Log()
3204 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003205
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003206 return nil
3207}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003208func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3209 flow := &oop.Flow{FlowId: flowID}
3210 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3211 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3212 "device-id": dh.device.Id})
3213 } else {
3214 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3215 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3216 "device-id": dh.device.Id,
3217 "err": err})
3218 }
3219 }
3220}
Girish Gowdracefae192020-03-19 18:14:10 -07003221
3222func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003223 for _, field := range flow_utils.GetOfbFields(flow) {
3224 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003225 return field.GetPort()
3226 }
3227 }
3228 return InvalidPort
3229}
3230
3231func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003232 for _, action := range flow_utils.GetActions(flow) {
3233 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003234 if out := action.GetOutput(); out != nil {
3235 return out.GetPort()
3236 }
3237 }
3238 }
3239 return InvalidPort
3240}
3241
Girish Gowdracefae192020-03-19 18:14:10 -07003242func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3243 inPort := getInPortFromFlow(flow)
3244 outPort := getOutPortFromFlow(flow)
3245
3246 if inPort == InvalidPort || outPort == InvalidPort {
3247 return inPort, outPort
3248 }
3249
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003250 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003251 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003252 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003253 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003254 return uniPort, outPort
3255 }
3256 }
3257 } else {
3258 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003259 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003260 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003261 return inPort, uniPort
3262 }
3263 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003264 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003265 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003266 return uniPort, outPort
3267 }
3268 }
3269 }
3270
3271 return InvalidPort, InvalidPort
3272}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003273
3274func extractOmciTransactionID(omciPkt []byte) uint16 {
3275 if len(omciPkt) > 3 {
3276 d := omciPkt[0:2]
3277 transid := binary.BigEndian.Uint16(d)
3278 return transid
3279 }
3280 return 0
3281}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003282
3283// StoreOnuDevice stores the onu parameters to the local cache.
3284func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3285 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3286 dh.onus.Store(onuKey, onuDevice)
3287}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003288
khenaidoodc2116e2021-10-19 17:33:19 -04003289func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003290 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003291 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003292 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003293 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003294 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003295 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003296 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003297 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3298 return nil, err
3299 }
3300 ID = device.ProxyAddress.GetOnuId()
3301 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3302 valueparam.Onu = &Onu
3303 valueparam.Value = value
3304
3305 // This API is unsupported until agent patch is added
3306 resp.Unsupported = uint32(value)
3307 _ = ctx
3308
3309 // Uncomment this code once agent changes are complete and tests
3310 /*
3311 resp, err = dh.Client.GetValue(ctx, valueparam)
3312 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003313 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003314 return nil, err
3315 }
3316 */
3317
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003318 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 -08003319 return resp, nil
3320}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003321
Akash Kankanala041a2122024-10-16 15:49:22 +05303322func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003323 // Default to NNI
3324 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003325 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003326 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003327 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003328 }
3329 return intfID
3330}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003331
Akash Kankanala041a2122024-10-16 15:49:22 +05303332func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003333 dh.perPonOnuIndicationChannelLock.Lock()
3334 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3335 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003336 return ch.indicationChannel
3337 }
3338 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303339 // We create a buffered channel here to avoid calling function to be blocked
3340 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003341 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003342 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003343 stopChannel: make(chan struct{}),
3344 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003345 dh.perPonOnuIndicationChannel[intfID] = channels
3346 dh.perPonOnuIndicationChannelLock.Unlock()
3347 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003348 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003349}
3350
Mahir Gunyelb0046752021-02-26 13:51:05 -08003351func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3352 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3353 dh.perPonOnuIndicationChannelLock.Lock()
3354 defer dh.perPonOnuIndicationChannelLock.Unlock()
3355 for _, v := range dh.perPonOnuIndicationChannel {
3356 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003357 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003358 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003359}
3360
Mahir Gunyelb0046752021-02-26 13:51:05 -08003361func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3362 ind := onuIndicationMsg{
3363 ctx: ctx,
3364 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003365 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003366 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003367 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303368 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003369}
3370
Mahir Gunyelb0046752021-02-26 13:51:05 -08003371func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003372 for {
3373 select {
3374 // process one indication per onu, before proceeding to the next one
3375 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003376 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003377 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003378 "ind": indication})
3379 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003380 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003381 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003382 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3383 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003384 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003385 }
3386 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003387 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003388 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3389 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003390 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003391 }
3392 }
3393 case <-onuChannels.stopChannel:
3394 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3395 close(onuChannels.indicationChannel)
3396 return
3397 }
3398 }
3399}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003400
3401// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3402// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003403func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003404 if dh.getDeviceDeletionInProgressFlag() {
3405 // The device itself is going to be reset as part of deletion. So nothing to be done.
3406 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3407 return nil
3408 }
3409
Girish Gowdra491a9c62021-01-06 16:43:07 -08003410 // Step1 : Fill McastFlowOrGroupControlBlock
3411 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3412 // Step3 : Wait on response channel for response
3413 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003414 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003415 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3416 errChan := make(chan error)
3417 var groupID uint32
3418 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3419 ctx: ctx,
3420 flowOrGroupAction: action,
3421 flow: flow,
3422 group: group,
3423 errChan: &errChan,
3424 }
3425 if flow != nil {
3426 groupID = flow_utils.GetGroup(flow)
3427 } else if group != nil {
3428 groupID = group.Desc.GroupId
3429 } else {
3430 return errors.New("flow-and-group-both-nil")
3431 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003432 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3433 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3434 // Derive the appropriate go routine to handle the request by a simple module operation.
3435 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3436 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3437 // Wait for handler to return error value
3438 err := <-errChan
3439 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3440 return err
3441 }
3442 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3443 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003444}
3445
3446// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003447func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003448 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003449 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003450 // block on the channel to receive an incoming mcast flow/group
3451 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003452 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3453 if mcastFlowOrGroupCb.flow != nil {
3454 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3455 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3456 log.Fields{"device-id": dh.device.Id,
3457 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003458 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3459 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3460 for _, flMgr := range dh.flowMgr {
3461 if flMgr != nil {
3462 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3463 break
3464 }
3465 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003466 // Pass the return value over the return channel
3467 *mcastFlowOrGroupCb.errChan <- err
3468 } else { // flow remove
3469 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3470 log.Fields{"device-id": dh.device.Id,
3471 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003472 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3473 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3474 for _, flMgr := range dh.flowMgr {
3475 if flMgr != nil {
3476 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3477 break
3478 }
3479 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003480 // Pass the return value over the return channel
3481 *mcastFlowOrGroupCb.errChan <- err
3482 }
3483 } else { // mcast group
3484 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3485 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3486 log.Fields{"device-id": dh.device.Id,
3487 "groupToAdd": mcastFlowOrGroupCb.group})
3488 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3489 // Pass the return value over the return channel
3490 *mcastFlowOrGroupCb.errChan <- err
3491 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3492 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3493 log.Fields{"device-id": dh.device.Id,
3494 "groupToModify": mcastFlowOrGroupCb.group})
3495 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3496 // Pass the return value over the return channel
3497 *mcastFlowOrGroupCb.errChan <- err
3498 } else { // group remove
3499 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3500 log.Fields{"device-id": dh.device.Id,
3501 "groupToRemove": mcastFlowOrGroupCb.group})
3502 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3503 // Pass the return value over the return channel
3504 *mcastFlowOrGroupCb.errChan <- err
3505 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003506 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003507 case <-stopHandler:
3508 dh.mcastHandlerRoutineActive[routineIndex] = false
3509 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003510 }
3511 }
3512}
kesavand62126212021-01-12 04:56:06 -05003513
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003514// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003515func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003516 for i, v := range dh.stopMcastHandlerRoutine {
3517 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003518 select {
3519 case v <- true:
3520 case <-time.After(time.Second * 5):
3521 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3522 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003523 }
3524 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003525
3526 if dh.incomingMcastFlowOrGroup != nil {
3527 for k := range dh.incomingMcastFlowOrGroup {
3528 if dh.incomingMcastFlowOrGroup[k] != nil {
3529 dh.incomingMcastFlowOrGroup[k] = nil
3530 }
3531 }
3532 dh.incomingMcastFlowOrGroup = nil
3533 }
3534
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003535 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003536 logger.Debug(ctx, "stopped all mcast handler routines")
3537}
3538
Akash Kankanala041a2122024-10-16 15:49:22 +05303539// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003540func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003541 singleValResp := extension.SingleGetValueResponse{
3542 Response: &extension.GetValueResponse{
3543 Response: &extension.GetValueResponse_PortCoutners{
3544 PortCoutners: &extension.GetOltPortCountersResponse{},
3545 },
3546 },
3547 }
3548
Akash Kankanala041a2122024-10-16 15:49:22 +05303549 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003550 return &extension.SingleGetValueResponse{
3551 Response: &extension.GetValueResponse{
3552 Status: status,
3553 ErrReason: reason,
3554 },
3555 }
3556 }
3557
3558 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3559 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303560 // send error response
kesavand62126212021-01-12 04:56:06 -05003561 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3562 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3563 }
3564 statIndChn := make(chan bool, 1)
3565 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3566 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303567 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003568
3569 go func() {
3570 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3571 if err != nil {
3572 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3573 }
3574 }()
3575 select {
3576 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303577 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003578 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3579 case <-time.After(oltPortInfoTimeout * time.Second):
3580 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3581 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3582 case <-ctx.Done():
3583 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3584 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3585 }
3586 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
Akash Kankanala041a2122024-10-16 15:49:22 +05303587 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003588 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003589 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3590 cmnni := dh.portStats.collectNNIMetrics(intfID)
3591 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303592 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003593 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3594 }
3595 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3596 return &singleValResp
kesavand62126212021-01-12 04:56:06 -05003597 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3598 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003599 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003600 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3601 cmpon := dh.portStats.collectPONMetrics(intfID)
3602 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303603 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003604 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3605 }
3606 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3607 return &singleValResp
3608 }
3609 }
3610 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3611}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303612
Akash Kankanala041a2122024-10-16 15:49:22 +05303613//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303614func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303615 singleValResp := extension.SingleGetValueResponse{
3616 Response: &extension.GetValueResponse{
3617 Status: extension.GetValueResponse_OK,
3618 Response: &extension.GetValueResponse_OffloadedAppsStats{
3619 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3620 },
3621 },
3622 }
3623
3624 return &singleValResp
3625}
3626
Akash Kankanala041a2122024-10-16 15:49:22 +05303627//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303628func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303629 singleValResp := extension.SingleSetValueResponse{
3630 Response: &extension.SetValueResponse{
3631 Status: extension.SetValueResponse_OK,
3632 },
3633 }
3634
3635 return &singleValResp
3636}
3637
Akash Kankanala041a2122024-10-16 15:49:22 +05303638//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303639func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303640 singleValResp := extension.SingleSetValueResponse{
3641 Response: &extension.SetValueResponse{
3642 Status: extension.SetValueResponse_OK,
3643 },
3644 }
3645
3646 return &singleValResp
3647}
3648
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303649func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303650 singleValResp := extension.SingleGetValueResponse{
3651 Response: &extension.GetValueResponse{
3652 Response: &extension.GetValueResponse_OnuPonCounters{
3653 OnuPonCounters: &extension.GetOnuCountersResponse{},
3654 },
3655 },
3656 }
3657
Akash Kankanala041a2122024-10-16 15:49:22 +05303658 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303659 return &extension.SingleGetValueResponse{
3660 Response: &extension.GetValueResponse{
3661 Status: status,
3662 ErrReason: reason,
3663 },
3664 }
3665 }
3666 intfID := onuPonInfo.IntfId
3667 onuID := onuPonInfo.OnuId
3668 onuKey := dh.formOnuKey(intfID, onuID)
3669
3670 if _, ok := dh.onus.Load(onuKey); !ok {
3671 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3672 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3673 }
3674 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3675 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3676 if cmnni == nil {
3677 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3678 }
3679 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3680 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303681}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003682
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303683func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3684 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3685 if err != nil {
3686 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3687 return nil, err
3688 }
3689 if onuGemInfo != nil {
3690 if len(onuGemInfo.UniPorts) == 0 {
3691 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
3692 return nil, err
3693 }
3694 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
3695 return onuGemInfo, nil
3696 }
3697 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
3698 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
3699}
3700
3701func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
3702 var err error
3703 var allocStats *oop.OnuAllocIdStatistics
3704 var onuGemStats *oop.GemPortStatistics
3705 for _, uni := range onuGemInfo.UniPorts {
3706 uniID := plt.UniIDFromPortNum(uni)
3707 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
3708 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
3709 if len(tpIDs) == 0 {
3710 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
3711 continue
3712 }
3713 for _, tpId := range tpIDs {
3714 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
3715 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
3716 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
3717 if techProfileInstance != nil {
3718 switch tpInst := techProfileInstance.(type) {
3719 case *tp_pb.TechProfileInstance:
3720 allocId := tpInst.UsScheduler.AllocId
3721 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
3722 allocStats, err = dh.Client.GetAllocIdStatistics(ctx, &onuAllocPkt)
3723 if err != nil {
3724 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
3725 return err
3726 }
3727 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
3728 allocIdInfo.AllocId = allocStats.AllocId
3729 allocIdInfo.RxBytes = allocStats.RxBytes
3730
3731 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
3732
3733 gemPorts := tpInst.UpstreamGemPortAttributeList
3734 for _, gem := range gemPorts {
3735 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
3736 onuGemStats, err = dh.Client.GetGemPortStatistics(ctx, &onuGemPkt)
3737 if err != nil {
3738 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
3739 return err
3740 }
3741 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
3742 gemStatsInfo.GemId = onuGemStats.GemportId
3743 gemStatsInfo.RxBytes = onuGemStats.RxBytes
3744 gemStatsInfo.RxPackets = onuGemStats.RxPackets
3745 gemStatsInfo.TxBytes = onuGemStats.TxBytes
3746 gemStatsInfo.TxPackets = onuGemStats.TxPackets
3747
3748 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
3749 }
3750 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
3751
3752 default:
3753 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
3754 return err
3755 }
3756 } else {
3757 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
3758 continue
3759 }
3760 }
3761 }
3762 return err
3763}
3764
3765//nolint:unparam
3766func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
3767 singleValResp := extension.SingleGetValueResponse{
3768 Response: &extension.GetValueResponse{
3769 Status: extension.GetValueResponse_OK,
3770 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
3771 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
3772 },
3773 },
3774 }
3775 errResp := func(status extension.GetValueResponse_Status,
3776 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3777 return &extension.SingleGetValueResponse{
3778 Response: &extension.GetValueResponse{
3779 Status: status,
3780 ErrReason: reason,
3781 },
3782 }
3783 }
3784
3785 var intfID, onuID uint32
3786 if onuDevice != nil {
3787 onuID = onuDevice.ProxyAddress.OnuId
3788 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
3789 }
3790
3791 onuKey := dh.formOnuKey(intfID, onuID)
3792 if _, ok := dh.onus.Load(onuKey); !ok {
3793 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
3794 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3795 }
3796 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
3797
3798 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
3799 if err == nil {
3800 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
3801 if err != nil {
3802 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3803 }
3804 } else {
3805 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3806 }
3807 return &singleValResp
3808}
3809
nikesh.krishnanc8473432023-06-14 12:14:54 +05303810func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05303811 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3812 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3813 if err != nil {
3814 return nil, err
3815 }
3816 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05303817}
3818
3819func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05303820 Intf := oop.Interface{IntfId: intfID}
3821 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3822 if err != nil {
3823 return nil, err
3824 }
3825 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05303826}
3827
Gamze Abaka85e9a142021-05-26 13:41:39 +00003828func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00003829 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3830 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3831 if err != nil {
3832 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3833 return generateSingleGetValueErrorResponse(err)
3834 }
3835 return &extension.SingleGetValueResponse{
3836 Response: &extension.GetValueResponse{
3837 Status: extension.GetValueResponse_OK,
3838 Response: &extension.GetValueResponse_RxPower{
3839 RxPower: &extension.GetRxPowerResponse{
3840 IntfId: rxPowerRequest.IntfId,
3841 OnuId: rxPowerRequest.OnuId,
3842 Status: rxPower.Status,
3843 FailReason: rxPower.FailReason.String(),
3844 RxPower: rxPower.RxPowerMeanDbm,
3845 },
3846 },
3847 },
3848 }
3849}
3850
praneeth nalmas55616d62023-02-06 09:19:18 +05303851func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05303852 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05303853 return &extension.SingleGetValueResponse{
3854 Response: &extension.GetValueResponse{
3855 Status: status,
3856 ErrReason: reason,
3857 },
3858 }
3859 }
3860
3861 resp := extension.SingleGetValueResponse{
3862 Response: &extension.GetValueResponse{
3863 Status: extension.GetValueResponse_OK,
3864 Response: &extension.GetValueResponse_OltRxPower{
3865 OltRxPower: &extension.GetOltRxPowerResponse{},
3866 },
3867 },
3868 }
3869
3870 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3871 portLabel := OltRxPowerRequest.PortLabel
3872 serialNumber := OltRxPowerRequest.OnuSn
3873
3874 portInfo := strings.Split(portLabel, "-")
3875 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3876
3877 if err != nil {
3878 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3879 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3880 }
3881
3882 if portInfo[0] != "pon" {
3883 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3884 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3885 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303886
3887 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05303888 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3889 if onuDev != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05303890 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3891 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3892 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05303893 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3894 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05303895 }
3896
3897 rxPowerValue := extension.RxPower{}
3898 rxPowerValue.OnuSn = onuDev.serialNumber
3899 rxPowerValue.Status = rxPower.GetStatus()
3900 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3901 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3902
3903 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05303904 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303905 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3906 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3907 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303908 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303909 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303910 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303911 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05303912 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3913 if err != nil {
3914 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3915 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303916 rxPowerValue := extension.RxPower{}
3917 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3918 rxPowerValue.Status = rxPower.GetStatus()
3919 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3920 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3921
3922 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3923 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303924 }
3925 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3926 return true
3927 })
3928 }
3929 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3930 return &resp
3931}
3932
Akash Kankanala041a2122024-10-16 15:49:22 +05303933// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00003934func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05303935 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00003936 return &extension.SingleGetValueResponse{
3937 Response: &extension.GetValueResponse{
3938 Status: status,
3939 ErrReason: reason,
3940 },
3941 }
3942 }
3943
3944 if err != nil {
3945 if e, ok := status.FromError(err); ok {
3946 switch e.Code() {
3947 case codes.Internal:
3948 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3949 case codes.DeadlineExceeded:
3950 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3951 case codes.Unimplemented:
3952 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3953 case codes.NotFound:
3954 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3955 }
3956 }
3957 }
3958
3959 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3960}
khenaidoo106c61a2021-08-11 18:05:46 -04003961
3962/*
3963Helper functions to communicate with Core
3964*/
3965
3966func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3967 cClient, err := dh.coreClient.GetCoreServiceClient()
3968 if err != nil || cClient == nil {
3969 return nil, err
3970 }
3971 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3972 defer cancel()
3973 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3974}
3975
khenaidoodc2116e2021-10-19 17:33:19 -04003976func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003977 cClient, err := dh.coreClient.GetCoreServiceClient()
3978 if err != nil || cClient == nil {
3979 return nil, err
3980 }
3981 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3982 defer cancel()
3983 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3984}
3985
khenaidoodc2116e2021-10-19 17:33:19 -04003986func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003987 cClient, err := dh.coreClient.GetCoreServiceClient()
3988 if err != nil || cClient == nil {
3989 return err
3990 }
3991 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3992 defer cancel()
3993 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3994 return err
3995}
3996
3997func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3998 cClient, err := dh.coreClient.GetCoreServiceClient()
3999 if err != nil || cClient == nil {
4000 return nil, err
4001 }
4002 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4003 defer cancel()
4004 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4005}
4006
4007func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4008 cClient, err := dh.coreClient.GetCoreServiceClient()
4009 if err != nil || cClient == nil {
4010 return nil, err
4011 }
4012 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4013 defer cancel()
4014 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4015}
4016
4017func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4018 cClient, err := dh.coreClient.GetCoreServiceClient()
4019 if err != nil || cClient == nil {
4020 return err
4021 }
4022 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4023 defer cancel()
4024 _, err = cClient.DeviceUpdate(subCtx, device)
4025 return err
4026}
4027
khenaidoodc2116e2021-10-19 17:33:19 -04004028func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004029 cClient, err := dh.coreClient.GetCoreServiceClient()
4030 if err != nil || cClient == nil {
4031 return nil, err
4032 }
4033 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4034 defer cancel()
4035 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4036}
4037
khenaidoodc2116e2021-10-19 17:33:19 -04004038func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004039 cClient, err := dh.coreClient.GetCoreServiceClient()
4040 if err != nil || cClient == nil {
4041 return err
4042 }
4043 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4044 defer cancel()
4045 _, err = cClient.SendPacketIn(subCtx, pkt)
4046 return err
4047}
4048
4049func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4050 cClient, err := dh.coreClient.GetCoreServiceClient()
4051 if err != nil || cClient == nil {
4052 return err
4053 }
4054 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4055 defer cancel()
4056 _, err = cClient.PortCreated(subCtx, port)
4057 return err
4058}
4059
khenaidoodc2116e2021-10-19 17:33:19 -04004060func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004061 cClient, err := dh.coreClient.GetCoreServiceClient()
4062 if err != nil || cClient == nil {
4063 return err
4064 }
4065 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4066 defer cancel()
4067 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4068 return err
4069}
4070
khenaidoodc2116e2021-10-19 17:33:19 -04004071func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004072 cClient, err := dh.coreClient.GetCoreServiceClient()
4073 if err != nil || cClient == nil {
4074 return err
4075 }
4076 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4077 defer cancel()
4078 _, err = cClient.PortStateUpdate(subCtx, portState)
4079 return err
4080}
4081
khenaidoodc2116e2021-10-19 17:33:19 -04004082func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004083 cClient, err := dh.coreClient.GetCoreServiceClient()
4084 if err != nil || cClient == nil {
4085 return nil, err
4086 }
4087 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4088 defer cancel()
4089 return cClient.GetDevicePort(subCtx, portFilter)
4090}
4091
nikesh.krishnanc8473432023-06-14 12:14:54 +05304092func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4093 cClient, err := dh.coreClient.GetCoreServiceClient()
4094 if err != nil || cClient == nil {
4095 return nil, err
4096 }
4097 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4098 defer cancel()
4099 return cClient.GetPorts(subCtx, portFilter)
4100}
4101
khenaidoo106c61a2021-08-11 18:05:46 -04004102/*
4103Helper functions to communicate with child adapter
4104*/
4105
khenaidoodc2116e2021-10-19 17:33:19 -04004106func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004107 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4108 if err != nil || aClient == nil {
4109 return err
4110 }
4111 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4112 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4113 defer cancel()
4114 _, err = aClient.OmciIndication(subCtx, response)
4115 return err
4116}
4117
khenaidoodc2116e2021-10-19 17:33:19 -04004118func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004119 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4120 if err != nil || aClient == nil {
4121 return err
4122 }
4123 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4124 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4125 defer cancel()
4126 _, err = aClient.OnuIndication(subCtx, onuInd)
4127 return err
4128}
4129
khenaidoodc2116e2021-10-19 17:33:19 -04004130func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004131 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4132 if err != nil || aClient == nil {
4133 return err
4134 }
4135 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4136 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4137 defer cancel()
4138 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4139 return err
4140}
4141
khenaidoodc2116e2021-10-19 17:33:19 -04004142func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004143 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4144 if err != nil || aClient == nil {
4145 return err
4146 }
4147 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4148 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4149 defer cancel()
4150 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4151 return err
4152}
4153
khenaidoodc2116e2021-10-19 17:33:19 -04004154func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004155 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4156 if err != nil || aClient == nil {
4157 return err
4158 }
4159 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4160 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4161 defer cancel()
4162 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4163 return err
4164}
4165
4166/*
4167Helper functions for remote communication
4168*/
4169
4170// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4171// supports is deleted
4172func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4173 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4174
4175 dh.lockChildAdapterClients.Lock()
4176 defer dh.lockChildAdapterClients.Unlock()
4177 if _, ok := dh.childAdapterClients[endpoint]; ok {
4178 // Already set
4179 return nil
4180 }
4181
4182 // Setup child's adapter grpc connection
4183 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004184 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4185 dh.cfg.AdapterEndpoint,
4186 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004187 "onu_inter_adapter_service.OnuInterAdapterService",
4188 dh.onuInterAdapterRestarted,
4189 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004190 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4191 return err
4192 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304193 retryCodes := []codes.Code{
4194 codes.Unavailable, // server is currently unavailable
4195 codes.DeadlineExceeded, // deadline for the operation was exceeded
4196 }
4197 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4198 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 -04004199
nikesh.krishnand9812542023-08-01 18:31:39 +05304200 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004201 // Wait until we have a connection to the child adapter.
4202 // Unlimited retries or until context expires
4203 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4204 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4205 for {
4206 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4207 if err == nil && client != nil {
4208 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4209 break
4210 }
4211 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4212 // Backoff
4213 if err = backoff.Backoff(subCtx); err != nil {
4214 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4215 break
4216 }
4217 }
4218 return nil
4219}
4220
khenaidoodc2116e2021-10-19 17:33:19 -04004221func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004222 // First check from cache
4223 dh.lockChildAdapterClients.RLock()
4224 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4225 dh.lockChildAdapterClients.RUnlock()
4226 return cgClient.GetOnuInterAdapterServiceClient()
4227 }
4228 dh.lockChildAdapterClients.RUnlock()
4229
4230 // Set the child connection - can occur on restarts
4231 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4232 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4233 cancel()
4234 if err != nil {
4235 return nil, err
4236 }
4237
4238 // Get the child client now
4239 dh.lockChildAdapterClients.RLock()
4240 defer dh.lockChildAdapterClients.RUnlock()
4241 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4242 return cgClient.GetOnuInterAdapterServiceClient()
4243 }
4244 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4245}
4246
4247func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4248 dh.lockChildAdapterClients.Lock()
4249 defer dh.lockChildAdapterClients.Unlock()
4250 for key, client := range dh.childAdapterClients {
4251 client.Stop(ctx)
4252 delete(dh.childAdapterClients, key)
4253 }
4254}
4255
khenaidooefff76e2021-12-15 16:51:30 -05004256// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4257func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4258 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004259 return nil
4260}
4261
khenaidooefff76e2021-12-15 16:51:30 -05004262// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4263func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4264 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004265 return nil
4266 }
khenaidooefff76e2021-12-15 16:51:30 -05004267 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004268}
Girish Gowdra950326e2021-11-05 12:43:24 -07004269
4270func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4271 dh.lockDevice.Lock()
4272 defer dh.lockDevice.Unlock()
4273 dh.isDeviceDeletionInProgress = flag
4274}
4275
4276func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4277 dh.lockDevice.RLock()
4278 defer dh.lockDevice.RUnlock()
4279 return dh.isDeviceDeletionInProgress
4280}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004281
4282// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4283// Returns false if waiting timed out.
4284func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4285 c := make(chan struct{})
4286 go func() {
4287 defer close(c)
4288 wg.Wait()
4289 }()
4290 select {
4291 case <-c:
4292 return true // completed normally
4293 case <-time.After(timeout):
4294 return false // timed out
4295 }
4296}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304297
4298func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4299 val, err := json.Marshal(signature)
4300 if err != nil {
4301 logger.Error(ctx, "failed-to-marshal")
4302 return
4303 }
4304 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4305 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4306 }
4307}
4308
4309func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4310 var signature uint32
4311
4312 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4313 if er == nil {
4314 if Value != nil {
4315 Val, er := kvstore.ToByte(Value.Value)
4316 if er != nil {
4317 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4318 return signature
4319 }
4320 if er = json.Unmarshal(Val, &signature); er != nil {
4321 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4322 return signature
4323 }
4324 }
4325 }
4326 return signature
4327}