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