blob: 9c82a8cdc16c793cb58a1a3aa81f132e2e9ae5ef [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
bseeniva43b5a912025-06-05 12:48:15 +05301791func (dh *DeviceHandler) handleOnuDiscoveryProcessingError(ctx context.Context, err error, sn string, tpInstExists bool) {
1792 if err != nil || tpInstExists {
1793 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1794 } else {
1795 // once the function completes set the value to false so that
1796 // we know the processing has inProcess.
1797 // Note that this is done after checking if we are already processing
1798 // to avoid changing the value from a different thread
1799 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1800 dh.discOnus.Store(sn, false)
1801 }
1802}
1803
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301804func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301805 var error error
bseeniva43b5a912025-06-05 12:48:15 +05301806 var tpInstExists bool
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301807
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301808 channelID := onuDiscInd.GetIntfId()
1809 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1810
1811 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301812 defer func() {
bseeniva43b5a912025-06-05 12:48:15 +05301813 dh.handleOnuDiscoveryProcessingError(ctx, error, sn, tpInstExists)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301814 }()
1815
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301816 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1817
bseeniva43b5a912025-06-05 12:48:15 +05301818 tpInstExists, error = dh.checkForResourceExistance(ctx, onuDiscInd, sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301819 if error != nil {
1820 return error
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301821 }
1822 if tpInstExists {
Akash Kankanala041a2122024-10-16 15:49:22 +05301823 // ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001824 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001825 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001826 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001827 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1828
1829 // if the ONU existed, handle the LOS Alarm
1830 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001831 if inProcess.(bool) {
1832 // if we're currently processing the ONU on a different thread, do nothing
1833 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1834 return nil
1835 }
1836 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1837 // then continue processing it
1838 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1839
1840 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001841 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301842 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001843 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001844
1845 // check the ONU is already know to the OLT
1846 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301847 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001848 ParentId: dh.device.Id,
1849 SerialNumber: sn,
1850 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001851
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301852 if error != nil {
1853 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1854 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001855 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 -08001856 switch e.Code() {
1857 case codes.Internal:
1858 // this probably means NOT FOUND, so just create a new device
1859 onuDevice = nil
1860 case codes.DeadlineExceeded:
1861 // if the call times out, cleanup and exit
1862 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301863 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1864 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001865 }
1866 }
1867 }
1868
1869 if onuDevice == nil {
1870 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001871 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001872 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001873 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301874 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001876
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301877 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001878 // if we can't create an ID in resource manager,
1879 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001880 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301881
1882 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001883 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301884 "serial-number": sn}, error)
1885 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001886 }
1887
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301888 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001889 ParentId: dh.device.Id,
1890 ParentPortNo: parentPortNo,
1891 ChannelId: channelID,
1892 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1893 SerialNumber: sn,
1894 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301895 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001896 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001897 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 +05301898
1899 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001900 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301901 "serial-number": sn}, error)
1902 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001903 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301904 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 +05301905 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
1906 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
1907 "onu-id": onuID,
1908 "device-id": dh.device.Id,
1909 "serial-number": sn}, error)
1910 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04001911 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001912 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301913 log.Fields{"onuDevice": onuDevice,
1914 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001915 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301916 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001917 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001918
khenaidoo106c61a2021-08-11 18:05:46 -04001919 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1920 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301921 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04001922 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301923 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301924 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
1925 return error
khenaidoo106c61a2021-08-11 18:05:46 -04001926 }
1927
Matteo Scandolo945e4012019-12-12 14:16:11 -08001928 // we can now use the existing ONU Id
1929 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05301930 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07001931 //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 +00001932 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001933 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301934 "intfId": onuDiscInd.GetIntfId(),
1935 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001936 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001937
khenaidoo106c61a2021-08-11 18:05:46 -04001938 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301939 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001940 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301941 log.Fields{"onu": onuDev,
1942 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001943
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301944 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001945 DeviceId: onuDevice.Id,
1946 ParentDeviceId: dh.device.Id,
1947 OperStatus: common.OperStatus_DISCOVERED,
1948 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301949 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301950 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001951 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301952 "serial-number": sn}, error)
1953 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07001954 }
khenaidoo106c61a2021-08-11 18:05:46 -04001955
Neha Sharma96b7bf22020-06-15 10:37:32 +00001956 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301957 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301958 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001959 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301960 "serial-number": sn}, error)
1961 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08001962 }
1963 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001964}
1965
Mahir Gunyelb0046752021-02-26 13:51:05 -08001966func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001967 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001968 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001969 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001970 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001971 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301972 log.Fields{"onuId": onuInd.OnuId,
1973 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301974 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001975 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001976 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001977 errFields := log.Fields{"device-id": dh.device.Id}
1978
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301979 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05301980 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07001981 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001982 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001983 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001984 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301985 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07001986 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001987 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001988 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001989 errFields["onu-id"] = onuInd.OnuId
1990 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001991 }
khenaidoodc2116e2021-10-19 17:33:19 -04001992 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001993 ParentId: dh.device.Id,
1994 SerialNumber: serialNumber,
1995 OnuId: onuInd.OnuId,
1996 ParentPortNo: ponPort,
1997 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001998 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001999
David K. Bainbridge794735f2020-02-11 21:01:37 -08002000 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002001 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002002 }
2003
David K. Bainbridge794735f2020-02-11 21:01:37 -08002004 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002005 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002006 "previousIntfId": onuDevice.ParentPortNo,
2007 "currentIntfId": ponPort})
2008 }
2009
2010 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002011 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302012 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2013 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302014 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002015 }
2016 if !foundInCache {
2017 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002018 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 -08002019 }
kesavand7cf3a052020-08-28 12:49:18 +05302020 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002021 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002022 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302023 }
2024 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002025 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002026 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002027 }
2028 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002029}
2030
Neha Sharma96b7bf22020-06-15 10:37:32 +00002031func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002032 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 -07002033 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2034 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2035 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2036 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002037 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002038 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2039 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002040 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002041 onuInd.OperState = "down"
2042 }
2043 }
2044
David K. Bainbridge794735f2020-02-11 21:01:37 -08002045 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002046 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002047 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 -04002048
khenaidoodc2116e2021-10-19 17:33:19 -04002049 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002050 DeviceId: onuDevice.Id,
2051 OnuIndication: onuInd,
2052 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002053 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302054 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002055 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002056 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002057 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002058 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002059 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002060 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002061 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002062 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002063 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002064}
2065
cuilin20187b2a8c32019-03-26 19:52:28 -07002066func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2067 if serialNum != nil {
2068 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002069 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002070 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002071}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002072func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2073 decodedStr, err := hex.DecodeString(serialNum[4:])
2074 if err != nil {
2075 return nil, err
2076 }
2077 return &oop.SerialNumber{
2078 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002079 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002080 }, nil
2081}
cuilin20187b2a8c32019-03-26 19:52:28 -07002082
2083func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002084 if len(vendorSpecific) > 3 {
2085 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2086 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2087 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2088 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2089 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2090 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2091 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2092 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2093 return tmp
2094 }
2095 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002096}
2097
Mahir Gunyela2e68702022-12-07 00:00:42 -08002098// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002099func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302100 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002101}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002102
Mahir Gunyela2e68702022-12-07 00:00:42 -08002103// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002104func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2105 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302106 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002107 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302108 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002109
khenaidoodc2116e2021-10-19 17:33:19 -04002110 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002111 ParentId: dh.device.Id,
2112 OnuId: onuID,
2113 ParentPortNo: parentPort,
2114 })
2115
Girish Gowdru0c588b22019-04-23 23:24:56 -04002116 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002117 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002118 "intf-id": parentPort,
2119 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002120 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002121 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 -08002122 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302123}
2124
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002125// SendPacketInToCore sends packet-in to core
2126// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2127// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002128func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002129 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002130 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002131 "port": logicalPort,
2132 "packet": hex.EncodeToString(packetPayload),
2133 "device-id": dh.device.Id,
2134 })
2135 }
khenaidoo106c61a2021-08-11 18:05:46 -04002136
khenaidoodc2116e2021-10-19 17:33:19 -04002137 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002138 DeviceId: dh.device.Id,
2139 Port: logicalPort,
2140 Packet: packetPayload,
2141 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302142 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002143 "source": "adapter",
2144 "destination": "core",
2145 "device-id": dh.device.Id,
2146 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002147 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002148 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002149 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002150 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002151 "packet": hex.EncodeToString(packetPayload),
2152 "device-id": dh.device.Id,
2153 })
2154 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002155 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002156}
2157
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002158// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002159func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002160 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002161
2162 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2163 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002164 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002165 }
2166
Kent Hagermane6ff1012020-07-14 15:07:53 -04002167 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002168 metrics := dh.metrics.GetSubscriberMetrics()
2169 for _, m := range pmConfigs.Metrics {
2170 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002171 }
2172 }
2173}
2174
khenaidoodc2116e2021-10-19 17:33:19 -04002175func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002176 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002177 var errorsList []error
2178
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002179 if dh.getDeviceDeletionInProgressFlag() {
2180 // The device itself is going to be reset as part of deletion. So nothing to be done.
2181 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2182 return nil
2183 }
2184
Girish Gowdru0c588b22019-04-23 23:24:56 -04002185 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002186 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302187 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002188
Neha Sharma96b7bf22020-06-15 10:37:32 +00002189 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302190 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002191 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302192 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002193 if flow_utils.HasGroup(flow) {
2194 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2195 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002196 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2197 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2198 } else {
2199 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2200 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002201 }
Girish Gowdracefae192020-03-19 18:14:10 -07002202 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002203 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302204 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002205 logger.Warnw(ctx, "flow-to-remove-not-found",
2206 log.Fields{
2207 "ponIf": intfID,
2208 "flowToRemove": flow,
2209 "error": err,
2210 })
2211 } else {
2212 errorsList = append(errorsList, err)
2213 }
Girish Gowdracefae192020-03-19 18:14:10 -07002214 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002215 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302216
2217 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302218 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002219 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302220 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002221 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302222 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002223 if flow_utils.HasGroup(flow) {
2224 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2225 } else {
yasin saplid0566272021-12-21 09:10:30 +00002226 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002227 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2228 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2229 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2230 } else {
yasin saplid0566272021-12-21 09:10:30 +00002231 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002232 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002233 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002234 if err != nil {
2235 errorsList = append(errorsList, err)
2236 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302237 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002238 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002239
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002240 return errorsList
2241}
2242
2243func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2244 var err error
2245 var errorsList []error
2246
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002247 if dh.getDeviceDeletionInProgressFlag() {
2248 // The device itself is going to be reset as part of deletion. So nothing to be done.
2249 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2250 return nil
2251 }
2252
Girish Gowdracefae192020-03-19 18:14:10 -07002253 // 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 +00002254 if groups != nil {
2255 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002256 // err = dh.groupMgr.AddGroup(ctx, group)
2257 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002258 if err != nil {
2259 errorsList = append(errorsList, err)
2260 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002261 }
2262 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002263 // err = dh.groupMgr.ModifyGroup(ctx, group)
2264 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002265 if err != nil {
2266 errorsList = append(errorsList, err)
2267 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002268 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002269 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002270 // err = dh.groupMgr.DeleteGroup(ctx, group)
2271 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002272 if err != nil {
2273 errorsList = append(errorsList, err)
2274 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002275 }
2276 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002277
2278 return errorsList
2279}
2280
Mahir Gunyela2e68702022-12-07 00:00:42 -08002281// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002282func (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 -07002283 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002284
2285 if dh.getDeviceDeletionInProgressFlag() {
2286 // The device itself is going to be reset as part of deletion. So nothing to be done.
2287 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2288 return nil
2289 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302290 if dh.transitionMap.currentDeviceState != deviceStateUp {
2291 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2292 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2293 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002294 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2295 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2296 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002297 if len(errorsList) > 0 {
2298 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2299 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002300 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002301 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302302}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002303
Mahir Gunyela2e68702022-12-07 00:00:42 -08002304// DisableDevice disables the given device
2305// It marks the following for the given device:
2306// Device-Handler Admin-State : down
2307// Device Port-State: UNKNOWN
2308// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002309func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002310 /* On device disable ,admin state update has to be done prior sending request to agent since
2311 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002312 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002313 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002314 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002315 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002316 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002317 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002318 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002319 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002320 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002321 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302322
2323 dh.discOnus = sync.Map{}
2324 dh.onus = sync.Map{}
2325
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002326 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302327 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002328 if dh.isCollectorActive {
2329 dh.stopCollector <- true
2330 }
2331 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302332
Neha Sharma96b7bf22020-06-15 10:37:32 +00002333 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002334 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302335 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302336 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002337
kdarapu1afeceb2020-02-12 01:38:09 -05002338 // 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 -04002339 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002340 DeviceId: cloned.Id,
2341 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2342 OperStatus: voltha.OperStatus_UNKNOWN,
2343 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002344 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002345 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002346 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002347 return nil
2348}
2349
Neha Sharma96b7bf22020-06-15 10:37:32 +00002350func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002351 // Update onu state as unreachable in onu adapter
2352 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302353 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002354
Akash Kankanala041a2122024-10-16 15:49:22 +05302355 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002356 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002357 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002358 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 -04002359 }
2360 if onuDevices != nil {
2361 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002362 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002363 DeviceId: onuDevice.Id,
2364 OnuIndication: &onuInd,
2365 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002366 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002367 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002368 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002369 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002370 }
2371 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002372}
2373
Mahir Gunyela2e68702022-12-07 00:00:42 -08002374// ReenableDevice re-enables the olt device after disable
2375// It marks the following for the given device:
2376// Device-Handler Admin-State : up
2377// Device Port-State: ACTIVE
2378// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002379func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302380 if dh.Client != nil {
2381 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2382 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2383 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2384 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302385 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302386 } else {
2387 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 +05302388 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002390
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002391 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002392 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002393 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002394 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002395 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2396 } else {
2397 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2398 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2399 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002400 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002401 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302402 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002403 device.OperStatus = voltha.OperStatus_ACTIVE
2404 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302405 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002406 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002407 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002408 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002409
khenaidoodc2116e2021-10-19 17:33:19 -04002410 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002411 DeviceId: device.Id,
2412 OperStatus: device.OperStatus,
2413 ConnStatus: device.ConnectStatus,
2414 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302415 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002416 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002417 "connect-status": device.ConnectStatus,
2418 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002419 }
kesavand39e0aa32020-01-28 20:58:50 -05002420
Neha Sharma96b7bf22020-06-15 10:37:32 +00002421 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002422
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002423 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002424}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002425
npujarec5762e2020-01-01 14:08:48 +05302426func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002427 var uniID uint32
2428 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002429 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302430 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002431 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002432 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002433 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002434 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2435 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2436 } else {
2437 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2438 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002439 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002440 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002441 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002442 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002443 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002444 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002445 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002446 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", 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-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002450 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002451 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002452 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002453 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002454 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302455 }
yasin saplibddc2d72022-02-08 13:10:17 +00002456 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2457 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002458 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002459 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302460 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002461 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002462 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002463 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 -03002464 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002465 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002466 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002467 if len(errs) > 0 {
2468 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2469 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2470 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002471 return nil
2472}
2473
Devmalya Paul495b94a2019-08-27 19:42:00 -04002474// 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 +05302475func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002476 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002477 /* Clear the KV store data associated with the all the UNI ports
2478 This clears up flow data and also resource map data for various
2479 other pon resources like alloc_id and gemport_id
2480 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002481
2482 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002483 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002484
Himani Chawla49a5d562020-11-25 11:53:44 +05302485 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002486 // Stop the Stats collector
2487 if dh.isCollectorActive {
2488 dh.stopCollector <- true
2489 }
2490 // stop the heartbeat check routine
2491 if dh.isHeartbeatCheckActive {
2492 dh.stopHeartbeatCheck <- true
2493 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302494 // Stop the read indication only if it the routine is active
2495 if dh.isReadIndicationRoutineActive {
2496 dh.stopIndications <- true
2497 }
2498 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302499
2500 err := dh.cleanupDeviceResources(ctx)
2501 if err != nil {
2502 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2503 } else {
2504 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2505 }
2506
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002507 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302508 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002509 if dh.Client != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302510 if _, err = dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002511 go func() {
2512 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302513 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2514 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002515 }
2516 }()
2517 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002518 }
2519 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002520 // There is no need to update the core about operation status and connection status of the OLT.
2521 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2522 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2523 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002524
khenaidoo7eb2d672021-10-22 19:08:50 -04002525 // Stop the adapter grpc clients for that parent device
2526 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002527 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002528}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002529
2530// StopAllFlowRoutines stops all flow routines
2531func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2532 var wg sync.WaitGroup
2533 wg.Add(1) // for the mcast routine below to finish
2534 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2535 for _, flMgr := range dh.flowMgr {
2536 if flMgr != nil {
2537 wg.Add(1) // for the flow handler routine below to finish
2538 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2539 }
2540 }
2541 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2542 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2543 } else {
2544 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2545 }
2546}
2547
Gustavo Silva41af9122022-10-11 11:05:13 -03002548func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2549 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002550 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302551 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002552 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002553 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002554 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002555 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002556 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2557 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302558 }
2559 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002560 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2561 errs = append(errs, err)
2562 }
2563 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2564 errs = append(errs, err)
2565 }
2566 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2567 errs = append(errs, err)
2568 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002569 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002570 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002571 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002572 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002573 }
2574 // Clean up NNI manager's data
2575 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2576 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002577 }
A R Karthick1f85b802019-10-11 05:06:05 +00002578
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002579 dh.CloseKVClient(ctx)
2580
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002581 // Take one final sweep at cleaning up KV store for the OLT device
2582 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002583 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2584 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002585 }
2586
Devmalya Paul495b94a2019-08-27 19:42:00 -04002587 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302588 dh.onus.Range(func(key interface{}, value interface{}) bool {
2589 dh.onus.Delete(key)
2590 return true
2591 })
2592
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002593 /*Delete discovered ONU map for the device*/
2594 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2595 dh.discOnus.Delete(key)
2596 return true
2597 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002598 if len(errs) > 0 {
2599 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2600 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2601 }
2602 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002603}
2604
Mahir Gunyela2e68702022-12-07 00:00:42 -08002605// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002606func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302607 if dh.Client != nil {
2608 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2609 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2610 }
2611 } else {
2612 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 -04002613 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302614
Neha Sharma96b7bf22020-06-15 10:37:32 +00002615 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002616 return nil
2617}
2618
David K. Bainbridge794735f2020-02-11 21:01:37 -08002619func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002620 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002621 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002622 "packet-indication": *packetIn,
2623 "device-id": dh.device.Id,
2624 "packet": hex.EncodeToString(packetIn.Pkt),
2625 })
2626 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002627 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2628 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2629 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002630 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002631 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002632 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002633 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002634 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002635 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002636 "logical-port-num": logicalPortNum,
2637 "device-id": dh.device.Id,
2638 "packet": hex.EncodeToString(packetIn.Pkt),
2639 })
2640 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002641
khenaidoodc2116e2021-10-19 17:33:19 -04002642 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002643 DeviceId: dh.device.Id,
2644 Port: logicalPortNum,
2645 Packet: packetIn.Pkt,
2646 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302647 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002648 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302649 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002650 "device-id": dh.device.Id,
2651 "packet": hex.EncodeToString(packetIn.Pkt),
2652 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002653 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002654
Matteo Scandolo92186242020-06-12 10:54:18 -07002655 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002656 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002657 "packet": hex.EncodeToString(packetIn.Pkt),
2658 "device-id": dh.device.Id,
2659 })
2660 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002661 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002662}
2663
Mahir Gunyela2e68702022-12-07 00:00:42 -08002664// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2665func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2666 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2667 if err != nil {
2668 return olterrors.NewErrInvalidValue(log.Fields{
2669 "egress-nni-port": egressPortNo,
2670 "device-id": dh.device.Id,
2671 }, err)
2672 }
2673 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2674
2675 if logger.V(log.DebugLevel) {
2676 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2677 "uplink-pkt": uplinkPkt,
2678 "packet": hex.EncodeToString(packet.Data),
2679 "device-id": dh.device.Id,
2680 })
2681 }
2682
2683 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2684 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2685 "packet": hex.EncodeToString(packet.Data),
2686 "device-id": dh.device.Id,
2687 }, err)
2688 }
2689 return nil
2690}
2691
2692// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2693func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2694 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2695 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2696 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2697 // Do not packet-out lldp packets on uni port.
2698 // ONOS has no clue about uni/nni ports, it just packets out on all
2699 // available ports on the Logical Switch. It should not be interested
2700 // in the UNI links.
2701 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2702 "device-id": dh.device.Id,
2703 })
2704 return nil
2705 }
2706 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2707 if innerEthType == 0x8100 {
2708 // q-in-q 802.1ad or 802.1q double tagged packet.
2709 // slice out the outer tag.
2710 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2711 if logger.V(log.DebugLevel) {
2712 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2713 "packet-data": hex.EncodeToString(packet.Data),
2714 "device-id": dh.device.Id,
2715 })
2716 }
2717 }
2718 }
2719 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2720 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2721 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2722 var gemPortID uint32
2723 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2724 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2725 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2726 }
2727 if err != nil {
2728 // In this case the openolt agent will receive the gemPortID as 0.
2729 // The agent tries to retrieve the gemPortID in this case.
2730 // This may not always succeed at the agent and packetOut may fail.
2731 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2732 "intf-id": intfID,
2733 "onu-id": onuID,
2734 "uni-id": uniID,
2735 "packet": hex.EncodeToString(packet.Data),
2736 "device-id": dh.device.Id,
2737 "error": err,
2738 })
2739 }
2740
2741 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2742 if logger.V(log.DebugLevel) {
2743 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2744 "egress-port-no": egressPortNo,
2745 "intf-id": intfID,
2746 "onu-id": onuID,
2747 "uni-id": uniID,
2748 "gem-port-id": gemPortID,
2749 "packet": hex.EncodeToString(packet.Data),
2750 "device-id": dh.device.Id,
2751 })
2752 }
2753
2754 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2755 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2756 "source": "adapter",
2757 "destination": "onu",
2758 "egress-port-number": egressPortNo,
2759 "intf-id": intfID,
2760 "oni-id": onuID,
2761 "uni-id": uniID,
2762 "gem-port-id": gemPortID,
2763 "packet": hex.EncodeToString(packet.Data),
2764 "device-id": dh.device.Id,
2765 }, err)
2766 }
2767 return nil
2768}
2769
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002770// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002771func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002772 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002773 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002774 "device-id": dh.device.Id,
2775 "egress-port-no": egressPortNo,
2776 "pkt-length": len(packet.Data),
2777 "packet": hex.EncodeToString(packet.Data),
2778 })
2779 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002780
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002781 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002782 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002783 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002784 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002785 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002786 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002787 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002788 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302789 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002790 "egressPortType": egressPortType,
2791 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302792 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002793 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002794 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002795 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002796}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002797
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002798func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2799 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002800}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302801
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002802func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002803 defer func() {
2804 dh.lockDevice.Lock()
2805 dh.isHeartbeatCheckActive = false
2806 dh.lockDevice.Unlock()
2807 }()
2808
2809 dh.lockDevice.Lock()
2810 dh.isHeartbeatCheckActive = true
2811 dh.lockDevice.Unlock()
2812
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302813 // start the heartbeat check towards the OLT.
2814 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302815 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302816
2817 for {
2818 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2819 select {
2820 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002821 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002822 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002823 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302824 if timerCheck == nil {
2825 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002826 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302827 }
2828 } else {
2829 if timerCheck != nil {
2830 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002831 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302832 }
2833 timerCheck = nil
2834 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302835 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2836 if dh.heartbeatSignature == 0 {
2837 // First time the signature will be 0, update the signture to DB when not found.
2838 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2839 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2840 }
2841 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2842
2843 dh.lockDevice.RLock()
2844 // Stop the read indication only if it the routine is active
2845 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2846 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2847 // on next execution of the readIndication routine.
2848 if !dh.isReadIndicationRoutineActive {
2849 // Start reading indications
2850 go func() {
2851 if err = dh.readIndications(ctx); err != nil {
2852 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2853 }
2854 }()
2855 }
2856 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302857 } else {
2858 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2859 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2860 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2861 go dh.updateStateRebooted(ctx)
2862 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302863 }
2864 cancel()
2865 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002866 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302867 return
2868 }
2869 }
2870}
2871
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002872func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002873 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002874 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002875 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2876 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2877 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2878 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2879 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002880 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002881 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2882 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002883 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302884
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302885 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002886 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002887 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002888 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002889 DeviceId: dh.device.Id,
2890 OperStatus: voltha.OperStatus_UNKNOWN,
2891 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2892 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002893 _ = 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 -04002894 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302895 /*
2896 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2897 DeviceId: dh.device.Id,
2898 PortTypeFilter: 0,
2899 OperStatus: voltha.OperStatus_UNKNOWN,
2900 }); err != nil {
2901 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2902 }
2903 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002904
Akash Kankanala041a2122024-10-16 15:49:22 +05302905 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002906 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002907 cloned := proto.Clone(device).(*voltha.Device)
2908 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2909 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2910 dh.device = cloned // update local copy of the device
2911 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002912
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002913 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002914 // Stop the Stats collector
2915 if dh.isCollectorActive {
2916 dh.stopCollector <- true
2917 }
2918 // stop the heartbeat check routine
2919 if dh.isHeartbeatCheckActive {
2920 dh.stopHeartbeatCheck <- true
2921 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002922 // Stop the read indication only if it the routine is active
2923 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2924 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2925 // on next execution of the readIndication routine.
2926 if dh.isReadIndicationRoutineActive {
2927 dh.stopIndications <- true
2928 }
2929 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002930 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302931 }
2932}
kesavand39e0aa32020-01-28 20:58:50 -05002933
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302934func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2935 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2936 if err != nil || device == nil {
2937 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2938 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2939 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2940 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2941 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2942 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2943 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2944 return
2945 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302946 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07002947 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302948
2949 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2950 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05302951 // First, stop the read indication and heartbeat check routines to prevent any delay
2952 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302953 dh.lockDevice.RLock()
2954 // Stop the read indication only if it the routine is active
2955 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2956 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2957 // on next execution of the readIndication routine.
2958 if dh.isReadIndicationRoutineActive {
2959 dh.stopIndications <- true
2960 }
2961 dh.lockDevice.RUnlock()
2962
bseenivad1c984b2025-01-09 12:54:44 +05302963 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2964 DeviceId: dh.device.Id,
2965 OperStatus: voltha.OperStatus_REBOOTED,
2966 ConnStatus: voltha.ConnectStatus_REACHABLE,
2967 }); err != nil {
2968 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2969 }
2970
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302971 //raise olt communication failure event
2972 raisedTs := time.Now().Unix()
2973 cloned := proto.Clone(device).(*voltha.Device)
2974 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2975 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2976 dh.device = cloned // update local copy of the device
2977 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2978
Gustavo Silva41af9122022-10-11 11:05:13 -03002979 if err := dh.cleanupDeviceResources(ctx); err != nil {
2980 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
2981 } else {
2982 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2983 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002984
2985 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302986 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002987 if dh.isCollectorActive {
2988 dh.stopCollector <- true
2989 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302990 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002991 if dh.isHeartbeatCheckActive {
2992 dh.stopHeartbeatCheck <- true
2993 }
2994 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302995
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002996 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302997
Akash Kankanala041a2122024-10-16 15:49:22 +05302998 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302999 dh.adapterPreviouslyConnected = false
3000 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303001 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3002 if err != nil || childDevices == nil {
3003 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3004 continue
3005 }
3006 if len(childDevices.Items) == 0 {
3007 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3008 break
3009 } else {
3010 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3011 time.Sleep(5 * time.Second)
3012 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303013 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303014 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003015 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303016 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3017 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303018}
3019
kesavand39e0aa32020-01-28 20:58:50 -05003020// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003021func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3022 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3023 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003024}
3025
3026// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003027func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3028 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3029 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003030}
3031
Mahir Gunyela2e68702022-12-07 00:00:42 -08003032// 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 +00003033func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3034 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003035 if port.GetType() == voltha.Port_ETHERNET_NNI {
3036 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003037 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303038 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303039 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003040 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003041 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003042 }
3043 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003044 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003045 ponIntf := &oop.Interface{IntfId: ponID}
3046 var operStatus voltha.OperStatus_Types
3047 if enablePort {
3048 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303049 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003050
3051 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303052 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003053 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003054 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003055 }
3056 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003057 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003059 } else {
3060 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303061 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003062 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303063 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003064 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003065 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003066 }
3067 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003068 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003070 }
khenaidoodc2116e2021-10-19 17:33:19 -04003071 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003072 DeviceId: dh.device.Id,
3073 PortType: voltha.Port_PON_OLT,
3074 PortNo: port.PortNo,
3075 OperStatus: operStatus,
3076 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303077 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303078 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003079 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003080 }
3081 return nil
3082}
3083
Mahir Gunyela2e68702022-12-07 00:00:42 -08003084// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003085func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003086 // Disable the port and update the oper_port_status to core
3087 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003088 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003089 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003090 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303091 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303092 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003093 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003094 }
3095 }
3096 }
3097 return nil
3098}
3099
Mahir Gunyela2e68702022-12-07 00:00:42 -08003100// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003101func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3102 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3103 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003104 if port.Type == voltha.Port_ETHERNET_NNI {
3105 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003106 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003107 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003108 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003109 }
3110 }
3111 if port.Type == voltha.Port_PON_OLT {
3112 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003113 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003114 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003115 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003116 }
3117 }
3118 }
3119}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003120
3121// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003122func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003123 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003124 if dh.getDeviceDeletionInProgressFlag() {
3125 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3126 // will reboot, so everything will be reset on the pOLT too.
3127 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3128 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3129 return nil
3130 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303131
3132 if dh.transitionMap.currentDeviceState != deviceStateUp {
3133 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})
3134 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3135 }
3136
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003137 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003138 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003139
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003140 var sn *oop.SerialNumber
3141 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003142 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303143 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003144 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303145 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003146 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003147 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003148
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003149 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303150 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003151 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003152 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3153 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3154 "device-id": dh.device.Id,
3155 "intf-id": intfID,
3156 "onuID": onuID,
3157 "err": err})
3158 } else {
3159 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003160 // Delete flows from device before schedulers and queue
3161 // Clear flowids for gem cache.
3162 removedFlows := []uint64{}
3163 for _, gem := range onuGem.GemPorts {
3164 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3165 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303166 // multiple gem port can have the same flow id
3167 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003168 var alreadyRemoved bool
3169 for _, removedFlowID := range removedFlows {
3170 if removedFlowID == flowID {
3171 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3172 alreadyRemoved = true
3173 break
3174 }
3175 }
3176 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003177 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003178 removedFlows = appendUnique64bit(removedFlows, flowID)
3179 }
3180 }
3181 }
3182 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3183 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003184 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3185 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3186 "device-id": dh.device.Id,
3187 "onu-device": onu,
3188 "err": err})
3189 }
yasin saplibddc2d72022-02-08 13:10:17 +00003190 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003191 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3192 "intf-id": intfID,
3193 "onu-device": onu,
3194 "onu-gem": onuGem,
3195 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303196 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003197 }
3198 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003199 }
yasin saplibddc2d72022-02-08 13:10:17 +00003200 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003201 dh.onus.Delete(onuKey)
3202 dh.discOnus.Delete(onuSn)
3203
3204 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003205 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303206 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303207 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003208 "onu-id": onuID}, err).Log()
3209 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003210
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003211 return nil
3212}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003213func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3214 flow := &oop.Flow{FlowId: flowID}
3215 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3216 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3217 "device-id": dh.device.Id})
3218 } else {
3219 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3220 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3221 "device-id": dh.device.Id,
3222 "err": err})
3223 }
3224 }
3225}
Girish Gowdracefae192020-03-19 18:14:10 -07003226
3227func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003228 for _, field := range flow_utils.GetOfbFields(flow) {
3229 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003230 return field.GetPort()
3231 }
3232 }
3233 return InvalidPort
3234}
3235
3236func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003237 for _, action := range flow_utils.GetActions(flow) {
3238 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003239 if out := action.GetOutput(); out != nil {
3240 return out.GetPort()
3241 }
3242 }
3243 }
3244 return InvalidPort
3245}
3246
Girish Gowdracefae192020-03-19 18:14:10 -07003247func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3248 inPort := getInPortFromFlow(flow)
3249 outPort := getOutPortFromFlow(flow)
3250
3251 if inPort == InvalidPort || outPort == InvalidPort {
3252 return inPort, outPort
3253 }
3254
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003255 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003256 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003257 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003258 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003259 return uniPort, outPort
3260 }
3261 }
3262 } else {
3263 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003264 if portType := plt.IntfIDToPortTypeName(outPort); 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 inPort, uniPort
3267 }
3268 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003269 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003270 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003271 return uniPort, outPort
3272 }
3273 }
3274 }
3275
3276 return InvalidPort, InvalidPort
3277}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003278
3279func extractOmciTransactionID(omciPkt []byte) uint16 {
3280 if len(omciPkt) > 3 {
3281 d := omciPkt[0:2]
3282 transid := binary.BigEndian.Uint16(d)
3283 return transid
3284 }
3285 return 0
3286}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003287
3288// StoreOnuDevice stores the onu parameters to the local cache.
3289func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3290 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3291 dh.onus.Store(onuKey, onuDevice)
3292}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003293
khenaidoodc2116e2021-10-19 17:33:19 -04003294func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003295 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003296 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003297 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003298 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003299 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003300 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003301 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003302 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3303 return nil, err
3304 }
3305 ID = device.ProxyAddress.GetOnuId()
3306 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3307 valueparam.Onu = &Onu
3308 valueparam.Value = value
3309
3310 // This API is unsupported until agent patch is added
3311 resp.Unsupported = uint32(value)
3312 _ = ctx
3313
3314 // Uncomment this code once agent changes are complete and tests
3315 /*
3316 resp, err = dh.Client.GetValue(ctx, valueparam)
3317 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003318 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003319 return nil, err
3320 }
3321 */
3322
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003323 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 -08003324 return resp, nil
3325}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003326
Akash Kankanala041a2122024-10-16 15:49:22 +05303327func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003328 // Default to NNI
3329 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003330 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003331 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003332 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003333 }
3334 return intfID
3335}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003336
Akash Kankanala041a2122024-10-16 15:49:22 +05303337func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003338 dh.perPonOnuIndicationChannelLock.Lock()
3339 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3340 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003341 return ch.indicationChannel
3342 }
3343 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303344 // We create a buffered channel here to avoid calling function to be blocked
3345 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003346 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003347 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003348 stopChannel: make(chan struct{}),
3349 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003350 dh.perPonOnuIndicationChannel[intfID] = channels
3351 dh.perPonOnuIndicationChannelLock.Unlock()
3352 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003353 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003354}
3355
Mahir Gunyelb0046752021-02-26 13:51:05 -08003356func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3357 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3358 dh.perPonOnuIndicationChannelLock.Lock()
3359 defer dh.perPonOnuIndicationChannelLock.Unlock()
3360 for _, v := range dh.perPonOnuIndicationChannel {
3361 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003362 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003363 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003364}
3365
Mahir Gunyelb0046752021-02-26 13:51:05 -08003366func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3367 ind := onuIndicationMsg{
3368 ctx: ctx,
3369 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003370 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003371 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003372 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303373 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003374}
3375
Mahir Gunyelb0046752021-02-26 13:51:05 -08003376func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003377 for {
3378 select {
3379 // process one indication per onu, before proceeding to the next one
3380 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003381 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003382 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003383 "ind": indication})
3384 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003385 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003386 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003387 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3388 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003389 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003390 }
3391 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003392 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003393 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3394 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003395 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003396 }
3397 }
3398 case <-onuChannels.stopChannel:
3399 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3400 close(onuChannels.indicationChannel)
3401 return
3402 }
3403 }
3404}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003405
3406// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3407// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003408func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003409 if dh.getDeviceDeletionInProgressFlag() {
3410 // The device itself is going to be reset as part of deletion. So nothing to be done.
3411 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3412 return nil
3413 }
3414
Girish Gowdra491a9c62021-01-06 16:43:07 -08003415 // Step1 : Fill McastFlowOrGroupControlBlock
3416 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3417 // Step3 : Wait on response channel for response
3418 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003419 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003420 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3421 errChan := make(chan error)
3422 var groupID uint32
3423 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3424 ctx: ctx,
3425 flowOrGroupAction: action,
3426 flow: flow,
3427 group: group,
3428 errChan: &errChan,
3429 }
3430 if flow != nil {
3431 groupID = flow_utils.GetGroup(flow)
3432 } else if group != nil {
3433 groupID = group.Desc.GroupId
3434 } else {
3435 return errors.New("flow-and-group-both-nil")
3436 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003437 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3438 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3439 // Derive the appropriate go routine to handle the request by a simple module operation.
3440 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3441 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3442 // Wait for handler to return error value
3443 err := <-errChan
3444 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3445 return err
3446 }
3447 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3448 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003449}
3450
3451// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003452func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003453 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003454 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003455 // block on the channel to receive an incoming mcast flow/group
3456 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003457 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3458 if mcastFlowOrGroupCb.flow != nil {
3459 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3460 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3461 log.Fields{"device-id": dh.device.Id,
3462 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003463 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3464 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3465 for _, flMgr := range dh.flowMgr {
3466 if flMgr != nil {
3467 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3468 break
3469 }
3470 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003471 // Pass the return value over the return channel
3472 *mcastFlowOrGroupCb.errChan <- err
3473 } else { // flow remove
3474 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3475 log.Fields{"device-id": dh.device.Id,
3476 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003477 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3478 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3479 for _, flMgr := range dh.flowMgr {
3480 if flMgr != nil {
3481 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3482 break
3483 }
3484 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003485 // Pass the return value over the return channel
3486 *mcastFlowOrGroupCb.errChan <- err
3487 }
3488 } else { // mcast group
3489 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3490 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3491 log.Fields{"device-id": dh.device.Id,
3492 "groupToAdd": mcastFlowOrGroupCb.group})
3493 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3494 // Pass the return value over the return channel
3495 *mcastFlowOrGroupCb.errChan <- err
3496 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3497 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3498 log.Fields{"device-id": dh.device.Id,
3499 "groupToModify": mcastFlowOrGroupCb.group})
3500 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3501 // Pass the return value over the return channel
3502 *mcastFlowOrGroupCb.errChan <- err
3503 } else { // group remove
3504 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3505 log.Fields{"device-id": dh.device.Id,
3506 "groupToRemove": mcastFlowOrGroupCb.group})
3507 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3508 // Pass the return value over the return channel
3509 *mcastFlowOrGroupCb.errChan <- err
3510 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003511 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003512 case <-stopHandler:
3513 dh.mcastHandlerRoutineActive[routineIndex] = false
3514 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003515 }
3516 }
3517}
kesavand62126212021-01-12 04:56:06 -05003518
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003519// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003520func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003521 for i, v := range dh.stopMcastHandlerRoutine {
3522 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003523 select {
3524 case v <- true:
3525 case <-time.After(time.Second * 5):
3526 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3527 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003528 }
3529 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003530
3531 if dh.incomingMcastFlowOrGroup != nil {
3532 for k := range dh.incomingMcastFlowOrGroup {
3533 if dh.incomingMcastFlowOrGroup[k] != nil {
3534 dh.incomingMcastFlowOrGroup[k] = nil
3535 }
3536 }
3537 dh.incomingMcastFlowOrGroup = nil
3538 }
3539
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003540 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003541 logger.Debug(ctx, "stopped all mcast handler routines")
3542}
3543
Akash Kankanala041a2122024-10-16 15:49:22 +05303544// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003545func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003546 singleValResp := extension.SingleGetValueResponse{
3547 Response: &extension.GetValueResponse{
3548 Response: &extension.GetValueResponse_PortCoutners{
3549 PortCoutners: &extension.GetOltPortCountersResponse{},
3550 },
3551 },
3552 }
3553
Akash Kankanala041a2122024-10-16 15:49:22 +05303554 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003555 return &extension.SingleGetValueResponse{
3556 Response: &extension.GetValueResponse{
3557 Status: status,
3558 ErrReason: reason,
3559 },
3560 }
3561 }
3562
3563 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3564 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303565 // send error response
kesavand62126212021-01-12 04:56:06 -05003566 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3567 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3568 }
3569 statIndChn := make(chan bool, 1)
3570 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3571 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303572 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003573
3574 go func() {
3575 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3576 if err != nil {
3577 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3578 }
3579 }()
3580 select {
3581 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303582 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003583 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3584 case <-time.After(oltPortInfoTimeout * time.Second):
3585 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3586 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3587 case <-ctx.Done():
3588 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3589 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3590 }
3591 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
Akash Kankanala041a2122024-10-16 15:49:22 +05303592 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003593 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003594 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3595 cmnni := dh.portStats.collectNNIMetrics(intfID)
3596 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303597 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003598 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3599 }
3600 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3601 return &singleValResp
kesavand62126212021-01-12 04:56:06 -05003602 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3603 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003604 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003605 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3606 cmpon := dh.portStats.collectPONMetrics(intfID)
3607 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303608 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003609 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3610 }
3611 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3612 return &singleValResp
3613 }
3614 }
3615 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3616}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303617
Akash Kankanala041a2122024-10-16 15:49:22 +05303618//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303619func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303620 singleValResp := extension.SingleGetValueResponse{
3621 Response: &extension.GetValueResponse{
3622 Status: extension.GetValueResponse_OK,
3623 Response: &extension.GetValueResponse_OffloadedAppsStats{
3624 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3625 },
3626 },
3627 }
3628
3629 return &singleValResp
3630}
3631
Akash Kankanala041a2122024-10-16 15:49:22 +05303632//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303633func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303634 singleValResp := extension.SingleSetValueResponse{
3635 Response: &extension.SetValueResponse{
3636 Status: extension.SetValueResponse_OK,
3637 },
3638 }
3639
3640 return &singleValResp
3641}
3642
Akash Kankanala041a2122024-10-16 15:49:22 +05303643//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303644func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303645 singleValResp := extension.SingleSetValueResponse{
3646 Response: &extension.SetValueResponse{
3647 Status: extension.SetValueResponse_OK,
3648 },
3649 }
3650
3651 return &singleValResp
3652}
3653
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303654func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303655 singleValResp := extension.SingleGetValueResponse{
3656 Response: &extension.GetValueResponse{
3657 Response: &extension.GetValueResponse_OnuPonCounters{
3658 OnuPonCounters: &extension.GetOnuCountersResponse{},
3659 },
3660 },
3661 }
3662
Akash Kankanala041a2122024-10-16 15:49:22 +05303663 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303664 return &extension.SingleGetValueResponse{
3665 Response: &extension.GetValueResponse{
3666 Status: status,
3667 ErrReason: reason,
3668 },
3669 }
3670 }
3671 intfID := onuPonInfo.IntfId
3672 onuID := onuPonInfo.OnuId
3673 onuKey := dh.formOnuKey(intfID, onuID)
3674
3675 if _, ok := dh.onus.Load(onuKey); !ok {
3676 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3677 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3678 }
3679 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3680 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3681 if cmnni == nil {
3682 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3683 }
3684 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3685 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303686}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003687
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303688func (dh *DeviceHandler) CheckOnuGemInfo(ctx context.Context, intfID uint32, onuID uint32) (*rsrcMgr.OnuGemInfo, error) {
3689 onuGemInfo, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
3690 if err != nil {
3691 logger.Errorw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuID})
3692 return nil, err
3693 }
3694 if onuGemInfo != nil {
3695 if len(onuGemInfo.UniPorts) == 0 {
3696 logger.Errorw(ctx, "No uniports present for the ONU", log.Fields{"onuID": onuID})
3697 return nil, err
3698 }
3699 logger.Debugw(ctx, "Received onuGemInfo", log.Fields{"onuID": onuID, "onuGemInfo": onuGemInfo})
3700 return onuGemInfo, nil
3701 }
3702 logger.Errorw(ctx, "Received nil onuGemInfo", log.Fields{"onuID": onuID})
3703 return nil, fmt.Errorf("onuGemInfo received as null, onuID : %d", onuID)
3704}
3705
3706func (dh *DeviceHandler) getAllocGemStats(ctx context.Context, intfID uint32, onuID uint32, onuGemInfo *rsrcMgr.OnuGemInfo, singleValResp *extension.SingleGetValueResponse) error {
3707 var err error
3708 var allocStats *oop.OnuAllocIdStatistics
3709 var onuGemStats *oop.GemPortStatistics
3710 for _, uni := range onuGemInfo.UniPorts {
3711 uniID := plt.UniIDFromPortNum(uni)
3712 uniPath := getUniPortPath(dh.device.Id, intfID, int32(onuID), int32(uniID))
3713 tpIDs := dh.resourceMgr[intfID].GetTechProfileIDForOnu(ctx, onuID, uniID)
3714 if len(tpIDs) == 0 {
3715 logger.Errorw(ctx, "No TPIDs present for the Uni", log.Fields{"onuID": onuID, "uniPort": uni})
3716 continue
3717 }
3718 for _, tpId := range tpIDs {
3719 tpPath := dh.flowMgr[intfID].getTPpath(ctx, uniPath, uint32(tpId))
3720 techProfileInstance, _ := dh.flowMgr[intfID].techprofile.GetTPInstance(ctx, tpPath)
3721 onuStatsFromOlt := extension.OnuAllocGemStatsFromOltResponse{}
3722 if techProfileInstance != nil {
3723 switch tpInst := techProfileInstance.(type) {
3724 case *tp_pb.TechProfileInstance:
3725 allocId := tpInst.UsScheduler.AllocId
3726 onuAllocPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, AllocId: allocId}
3727 allocStats, err = dh.Client.GetAllocIdStatistics(ctx, &onuAllocPkt)
3728 if err != nil {
3729 logger.Errorw(ctx, "Error received from openolt for GetAllocIdStatistics", log.Fields{"onuID": onuID, "AllodId": allocId, "Error": err})
3730 return err
3731 }
3732 allocIdInfo := extension.OnuAllocIdInfoFromOlt{}
3733 allocIdInfo.AllocId = allocStats.AllocId
3734 allocIdInfo.RxBytes = allocStats.RxBytes
3735
3736 onuStatsFromOlt.AllocIdInfo = &allocIdInfo
3737
3738 gemPorts := tpInst.UpstreamGemPortAttributeList
3739 for _, gem := range gemPorts {
3740 onuGemPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, GemportId: gem.GemportId}
3741 onuGemStats, err = dh.Client.GetGemPortStatistics(ctx, &onuGemPkt)
3742 if err != nil {
3743 logger.Errorw(ctx, "Error received from openolt for GetGemPortStatistics", log.Fields{"onuID": onuID, "GemPortId": gem.GemportId, "Error": err})
3744 return err
3745 }
3746 gemStatsInfo := extension.OnuGemPortInfoFromOlt{}
3747 gemStatsInfo.GemId = onuGemStats.GemportId
3748 gemStatsInfo.RxBytes = onuGemStats.RxBytes
3749 gemStatsInfo.RxPackets = onuGemStats.RxPackets
3750 gemStatsInfo.TxBytes = onuGemStats.TxBytes
3751 gemStatsInfo.TxPackets = onuGemStats.TxPackets
3752
3753 onuStatsFromOlt.GemPortInfo = append(onuStatsFromOlt.GemPortInfo, &gemStatsInfo)
3754 }
3755 singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo = append(singleValResp.Response.GetOnuStatsFromOltResponse().AllocGemStatsInfo, &onuStatsFromOlt)
3756
3757 default:
3758 logger.Errorw(ctx, "Invalid Techprofile type received", log.Fields{"onuID": onuID, "TpId": tpId})
3759 return err
3760 }
3761 } else {
3762 logger.Errorw(ctx, "No TpInstance found for the TpID", log.Fields{"onuID": onuID, "TpId": tpId})
3763 continue
3764 }
3765 }
3766 }
3767 return err
3768}
3769
3770//nolint:unparam
3771func (dh *DeviceHandler) getOnuStatsFromOlt(ctx context.Context, onuInfo *extension.GetOnuStatsFromOltRequest, onuDevice *voltha.Device) *extension.SingleGetValueResponse {
3772 singleValResp := extension.SingleGetValueResponse{
3773 Response: &extension.GetValueResponse{
3774 Status: extension.GetValueResponse_OK,
3775 Response: &extension.GetValueResponse_OnuStatsFromOltResponse{
3776 OnuStatsFromOltResponse: &extension.GetOnuStatsFromOltResponse{},
3777 },
3778 },
3779 }
3780 errResp := func(status extension.GetValueResponse_Status,
3781 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3782 return &extension.SingleGetValueResponse{
3783 Response: &extension.GetValueResponse{
3784 Status: status,
3785 ErrReason: reason,
3786 },
3787 }
3788 }
3789
3790 var intfID, onuID uint32
3791 if onuDevice != nil {
3792 onuID = onuDevice.ProxyAddress.OnuId
3793 intfID = plt.PortNoToIntfID(onuDevice.ParentPortNo, voltha.Port_PON_OLT)
3794 }
3795
3796 onuKey := dh.formOnuKey(intfID, onuID)
3797 if _, ok := dh.onus.Load(onuKey); !ok {
3798 logger.Errorw(ctx, "getOnuStatsFromOlt request received for invalid device", log.Fields{"deviceId": onuDevice.Id, "intfID": intfID, "onuID": onuID})
3799 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3800 }
3801 logger.Debugw(ctx, "getOnuStatsFromOlt request received", log.Fields{"intfID": intfID, "onuID": onuID})
3802
3803 onuGemInfo, err := dh.CheckOnuGemInfo(ctx, intfID, onuID)
3804 if err == nil {
3805 err = dh.getAllocGemStats(ctx, intfID, onuID, onuGemInfo, &singleValResp)
3806 if err != nil {
3807 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3808 }
3809 } else {
3810 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3811 }
3812 return &singleValResp
3813}
3814
nikesh.krishnanc8473432023-06-14 12:14:54 +05303815func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05303816 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3817 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3818 if err != nil {
3819 return nil, err
3820 }
3821 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05303822}
3823
3824func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05303825 Intf := oop.Interface{IntfId: intfID}
3826 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3827 if err != nil {
3828 return nil, err
3829 }
3830 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05303831}
3832
Gamze Abaka85e9a142021-05-26 13:41:39 +00003833func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00003834 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3835 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3836 if err != nil {
3837 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3838 return generateSingleGetValueErrorResponse(err)
3839 }
3840 return &extension.SingleGetValueResponse{
3841 Response: &extension.GetValueResponse{
3842 Status: extension.GetValueResponse_OK,
3843 Response: &extension.GetValueResponse_RxPower{
3844 RxPower: &extension.GetRxPowerResponse{
3845 IntfId: rxPowerRequest.IntfId,
3846 OnuId: rxPowerRequest.OnuId,
3847 Status: rxPower.Status,
3848 FailReason: rxPower.FailReason.String(),
3849 RxPower: rxPower.RxPowerMeanDbm,
3850 },
3851 },
3852 },
3853 }
3854}
3855
praneeth nalmas55616d62023-02-06 09:19:18 +05303856func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05303857 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05303858 return &extension.SingleGetValueResponse{
3859 Response: &extension.GetValueResponse{
3860 Status: status,
3861 ErrReason: reason,
3862 },
3863 }
3864 }
3865
3866 resp := extension.SingleGetValueResponse{
3867 Response: &extension.GetValueResponse{
3868 Status: extension.GetValueResponse_OK,
3869 Response: &extension.GetValueResponse_OltRxPower{
3870 OltRxPower: &extension.GetOltRxPowerResponse{},
3871 },
3872 },
3873 }
3874
3875 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3876 portLabel := OltRxPowerRequest.PortLabel
3877 serialNumber := OltRxPowerRequest.OnuSn
3878
3879 portInfo := strings.Split(portLabel, "-")
3880 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3881
3882 if err != nil {
3883 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3884 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3885 }
3886
3887 if portInfo[0] != "pon" {
3888 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3889 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3890 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303891
3892 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05303893 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3894 if onuDev != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05303895 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3896 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3897 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05303898 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3899 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05303900 }
3901
3902 rxPowerValue := extension.RxPower{}
3903 rxPowerValue.OnuSn = onuDev.serialNumber
3904 rxPowerValue.Status = rxPower.GetStatus()
3905 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3906 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3907
3908 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05303909 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303910 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3911 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3912 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303913 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303914 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303915 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303916 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05303917 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3918 if err != nil {
3919 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3920 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303921 rxPowerValue := extension.RxPower{}
3922 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3923 rxPowerValue.Status = rxPower.GetStatus()
3924 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3925 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3926
3927 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3928 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303929 }
3930 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3931 return true
3932 })
3933 }
3934 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3935 return &resp
3936}
3937
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05303938func (dh *DeviceHandler) getPonPortStats(ctx context.Context, ponStatsRequest *extension.GetPonStatsRequest) *extension.SingleGetValueResponse {
3939 errResp := func(status extension.GetValueResponse_Status,
3940 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3941 return &extension.SingleGetValueResponse{
3942 Response: &extension.GetValueResponse{
3943 Status: status,
3944 ErrReason: reason,
3945 },
3946 }
3947 }
3948
3949 resp := extension.SingleGetValueResponse{
3950 Response: &extension.GetValueResponse{
3951 Status: extension.GetValueResponse_OK,
3952 Response: &extension.GetValueResponse_OltPonStatsResponse{
3953 OltPonStatsResponse: &extension.GetPonStatsResponse{},
3954 },
3955 },
3956 }
3957
3958 portLabel := ponStatsRequest.GetPortLabel()
3959 logger.Debugw(ctx, "getPonPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
3960
3961 portInfo := strings.Split(portLabel, "-")
3962 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3963
3964 if err != nil {
3965 logger.Errorw(ctx, "getPonPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3966 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3967 }
3968
3969 if portInfo[0] != "pon" {
3970 logger.Errorw(ctx, "getPonPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
3971 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3972 }
3973
3974 Interface := oop.Interface{IntfId: uint32(portNumber)}
3975 ponStats, err := dh.Client.GetPonPortStatistics(ctx, &Interface)
3976 if err != nil {
3977 logger.Errorw(ctx, "error-while-getting-pon-port-stats", log.Fields{"IntfId": portNumber, "err": err})
3978 return generateSingleGetValueErrorResponse(err)
3979 }
3980
3981 ponPortStats := resp.Response.GetOltPonStatsResponse()
3982 ponPortStats.PonPort = uint32(portNumber)
3983 ponPortStats.PortStatistics = ponStats
3984
3985 logger.Infow(ctx, "getPonPortStats response ", log.Fields{"Response": resp})
3986 return &resp
3987}
3988
3989func (dh *DeviceHandler) getNniPortStats(ctx context.Context, nniStatsRequest *extension.GetNNIStatsRequest) *extension.SingleGetValueResponse {
3990 errResp := func(status extension.GetValueResponse_Status,
3991 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3992 return &extension.SingleGetValueResponse{
3993 Response: &extension.GetValueResponse{
3994 Status: status,
3995 ErrReason: reason,
3996 },
3997 }
3998 }
3999
4000 resp := extension.SingleGetValueResponse{
4001 Response: &extension.GetValueResponse{
4002 Status: extension.GetValueResponse_OK,
4003 Response: &extension.GetValueResponse_OltNniStatsResponse{
4004 OltNniStatsResponse: &extension.GetNNIStatsResponse{},
4005 },
4006 },
4007 }
4008
4009 portLabel := nniStatsRequest.GetPortLabel()
4010 logger.Debugw(ctx, "getNniPortStats", log.Fields{"portLabel": portLabel, "device-id": dh.device.Id})
4011
4012 portInfo := strings.Split(portLabel, "-")
4013 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
4014
4015 if err != nil {
4016 logger.Errorw(ctx, "getNniPortStats invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
4017 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
4018 }
4019
4020 if portInfo[0] != "nni" {
4021 logger.Errorw(ctx, "getNniPortStats invalid portType", log.Fields{"oltPortType": portInfo[0]})
4022 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
4023 }
4024
4025 Interface := oop.Interface{IntfId: uint32(portNumber)}
4026 nniStats, err := dh.Client.GetNniPortStatistics(ctx, &Interface)
4027 if err != nil {
4028 logger.Errorw(ctx, "error-while-getting-nni-port-stats", log.Fields{"PortNo": portNumber, "err": err})
4029 return generateSingleGetValueErrorResponse(err)
4030 }
4031
4032 nniPortStats := resp.Response.GetOltNniStatsResponse()
4033 nniPortStats.NniPort = uint32(portNumber)
4034 nniPortStats.PortStatistics = nniStats
4035
4036 logger.Infow(ctx, "getNniPortStats response ", log.Fields{"Response": resp})
4037 return &resp
4038}
4039
Akash Kankanala041a2122024-10-16 15:49:22 +05304040// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00004041func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05304042 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00004043 return &extension.SingleGetValueResponse{
4044 Response: &extension.GetValueResponse{
4045 Status: status,
4046 ErrReason: reason,
4047 },
4048 }
4049 }
4050
4051 if err != nil {
4052 if e, ok := status.FromError(err); ok {
4053 switch e.Code() {
4054 case codes.Internal:
4055 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
4056 case codes.DeadlineExceeded:
4057 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
4058 case codes.Unimplemented:
4059 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
4060 case codes.NotFound:
4061 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
4062 }
4063 }
4064 }
4065
4066 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
4067}
khenaidoo106c61a2021-08-11 18:05:46 -04004068
4069/*
4070Helper functions to communicate with Core
4071*/
4072
4073func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
4074 cClient, err := dh.coreClient.GetCoreServiceClient()
4075 if err != nil || cClient == nil {
4076 return nil, err
4077 }
4078 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4079 defer cancel()
4080 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
4081}
4082
khenaidoodc2116e2021-10-19 17:33:19 -04004083func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004084 cClient, err := dh.coreClient.GetCoreServiceClient()
4085 if err != nil || cClient == nil {
4086 return nil, err
4087 }
4088 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4089 defer cancel()
4090 return cClient.GetChildDevice(subCtx, childDeviceFilter)
4091}
4092
khenaidoodc2116e2021-10-19 17:33:19 -04004093func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004094 cClient, err := dh.coreClient.GetCoreServiceClient()
4095 if err != nil || cClient == nil {
4096 return err
4097 }
4098 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4099 defer cancel()
4100 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
4101 return err
4102}
4103
4104func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
4105 cClient, err := dh.coreClient.GetCoreServiceClient()
4106 if err != nil || cClient == nil {
4107 return nil, err
4108 }
4109 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4110 defer cancel()
4111 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
4112}
4113
4114func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
4115 cClient, err := dh.coreClient.GetCoreServiceClient()
4116 if err != nil || cClient == nil {
4117 return nil, err
4118 }
4119 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4120 defer cancel()
4121 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
4122}
4123
4124func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
4125 cClient, err := dh.coreClient.GetCoreServiceClient()
4126 if err != nil || cClient == nil {
4127 return err
4128 }
4129 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4130 defer cancel()
4131 _, err = cClient.DeviceUpdate(subCtx, device)
4132 return err
4133}
4134
khenaidoodc2116e2021-10-19 17:33:19 -04004135func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004136 cClient, err := dh.coreClient.GetCoreServiceClient()
4137 if err != nil || cClient == nil {
4138 return nil, err
4139 }
4140 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4141 defer cancel()
4142 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
4143}
4144
khenaidoodc2116e2021-10-19 17:33:19 -04004145func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004146 cClient, err := dh.coreClient.GetCoreServiceClient()
4147 if err != nil || cClient == nil {
4148 return err
4149 }
4150 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4151 defer cancel()
4152 _, err = cClient.SendPacketIn(subCtx, pkt)
4153 return err
4154}
4155
4156func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
4157 cClient, err := dh.coreClient.GetCoreServiceClient()
4158 if err != nil || cClient == nil {
4159 return err
4160 }
4161 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4162 defer cancel()
4163 _, err = cClient.PortCreated(subCtx, port)
4164 return err
4165}
4166
khenaidoodc2116e2021-10-19 17:33:19 -04004167func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004168 cClient, err := dh.coreClient.GetCoreServiceClient()
4169 if err != nil || cClient == nil {
4170 return err
4171 }
4172 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4173 defer cancel()
4174 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
4175 return err
4176}
4177
khenaidoodc2116e2021-10-19 17:33:19 -04004178func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004179 cClient, err := dh.coreClient.GetCoreServiceClient()
4180 if err != nil || cClient == nil {
4181 return err
4182 }
4183 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4184 defer cancel()
4185 _, err = cClient.PortStateUpdate(subCtx, portState)
4186 return err
4187}
4188
khenaidoodc2116e2021-10-19 17:33:19 -04004189func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004190 cClient, err := dh.coreClient.GetCoreServiceClient()
4191 if err != nil || cClient == nil {
4192 return nil, err
4193 }
4194 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4195 defer cancel()
4196 return cClient.GetDevicePort(subCtx, portFilter)
4197}
4198
nikesh.krishnanc8473432023-06-14 12:14:54 +05304199func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4200 cClient, err := dh.coreClient.GetCoreServiceClient()
4201 if err != nil || cClient == nil {
4202 return nil, err
4203 }
4204 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4205 defer cancel()
4206 return cClient.GetPorts(subCtx, portFilter)
4207}
4208
khenaidoo106c61a2021-08-11 18:05:46 -04004209/*
4210Helper functions to communicate with child adapter
4211*/
4212
khenaidoodc2116e2021-10-19 17:33:19 -04004213func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004214 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4215 if err != nil || aClient == nil {
4216 return err
4217 }
4218 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4219 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4220 defer cancel()
4221 _, err = aClient.OmciIndication(subCtx, response)
4222 return err
4223}
4224
khenaidoodc2116e2021-10-19 17:33:19 -04004225func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004226 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4227 if err != nil || aClient == nil {
4228 return err
4229 }
4230 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4231 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4232 defer cancel()
4233 _, err = aClient.OnuIndication(subCtx, onuInd)
4234 return err
4235}
4236
khenaidoodc2116e2021-10-19 17:33:19 -04004237func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004238 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4239 if err != nil || aClient == nil {
4240 return err
4241 }
4242 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4243 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4244 defer cancel()
4245 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4246 return err
4247}
4248
khenaidoodc2116e2021-10-19 17:33:19 -04004249func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004250 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4251 if err != nil || aClient == nil {
4252 return err
4253 }
4254 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4255 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4256 defer cancel()
4257 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4258 return err
4259}
4260
khenaidoodc2116e2021-10-19 17:33:19 -04004261func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004262 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4263 if err != nil || aClient == nil {
4264 return err
4265 }
4266 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4267 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4268 defer cancel()
4269 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4270 return err
4271}
4272
4273/*
4274Helper functions for remote communication
4275*/
4276
4277// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4278// supports is deleted
4279func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4280 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4281
4282 dh.lockChildAdapterClients.Lock()
4283 defer dh.lockChildAdapterClients.Unlock()
4284 if _, ok := dh.childAdapterClients[endpoint]; ok {
4285 // Already set
4286 return nil
4287 }
4288
4289 // Setup child's adapter grpc connection
4290 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004291 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4292 dh.cfg.AdapterEndpoint,
4293 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004294 "onu_inter_adapter_service.OnuInterAdapterService",
4295 dh.onuInterAdapterRestarted,
4296 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004297 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4298 return err
4299 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304300 retryCodes := []codes.Code{
4301 codes.Unavailable, // server is currently unavailable
4302 codes.DeadlineExceeded, // deadline for the operation was exceeded
4303 }
4304 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4305 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 -04004306
nikesh.krishnand9812542023-08-01 18:31:39 +05304307 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004308 // Wait until we have a connection to the child adapter.
4309 // Unlimited retries or until context expires
4310 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4311 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4312 for {
4313 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4314 if err == nil && client != nil {
4315 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4316 break
4317 }
4318 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4319 // Backoff
4320 if err = backoff.Backoff(subCtx); err != nil {
4321 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4322 break
4323 }
4324 }
4325 return nil
4326}
4327
khenaidoodc2116e2021-10-19 17:33:19 -04004328func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004329 // First check from cache
4330 dh.lockChildAdapterClients.RLock()
4331 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4332 dh.lockChildAdapterClients.RUnlock()
4333 return cgClient.GetOnuInterAdapterServiceClient()
4334 }
4335 dh.lockChildAdapterClients.RUnlock()
4336
4337 // Set the child connection - can occur on restarts
4338 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4339 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4340 cancel()
4341 if err != nil {
4342 return nil, err
4343 }
4344
4345 // Get the child client now
4346 dh.lockChildAdapterClients.RLock()
4347 defer dh.lockChildAdapterClients.RUnlock()
4348 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4349 return cgClient.GetOnuInterAdapterServiceClient()
4350 }
4351 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4352}
4353
4354func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4355 dh.lockChildAdapterClients.Lock()
4356 defer dh.lockChildAdapterClients.Unlock()
4357 for key, client := range dh.childAdapterClients {
4358 client.Stop(ctx)
4359 delete(dh.childAdapterClients, key)
4360 }
4361}
4362
khenaidooefff76e2021-12-15 16:51:30 -05004363// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4364func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4365 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004366 return nil
4367}
4368
khenaidooefff76e2021-12-15 16:51:30 -05004369// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4370func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4371 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004372 return nil
4373 }
khenaidooefff76e2021-12-15 16:51:30 -05004374 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004375}
Girish Gowdra950326e2021-11-05 12:43:24 -07004376
4377func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4378 dh.lockDevice.Lock()
4379 defer dh.lockDevice.Unlock()
4380 dh.isDeviceDeletionInProgress = flag
4381}
4382
4383func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4384 dh.lockDevice.RLock()
4385 defer dh.lockDevice.RUnlock()
4386 return dh.isDeviceDeletionInProgress
4387}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004388
4389// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4390// Returns false if waiting timed out.
4391func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4392 c := make(chan struct{})
4393 go func() {
4394 defer close(c)
4395 wg.Wait()
4396 }()
4397 select {
4398 case <-c:
4399 return true // completed normally
4400 case <-time.After(timeout):
4401 return false // timed out
4402 }
4403}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304404
4405func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4406 val, err := json.Marshal(signature)
4407 if err != nil {
4408 logger.Error(ctx, "failed-to-marshal")
4409 return
4410 }
4411 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4412 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4413 }
4414}
4415
4416func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4417 var signature uint32
4418
4419 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4420 if er == nil {
4421 if Value != nil {
4422 Val, er := kvstore.ToByte(Value.Value)
4423 if er != nil {
4424 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4425 return signature
4426 }
4427 if er = json.Unmarshal(Val, &signature); er != nil {
4428 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4429 return signature
4430 }
4431 }
4432 }
4433 return signature
4434}