blob: b12dca16fecd37e88f0419500e591916156fcbe6 [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"
60 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070061 "google.golang.org/grpc"
nikesh.krishnand9812542023-08-01 18:31:39 +053062 codes "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040063 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053064)
65
salmansiddiqui7ac62132019-08-22 03:58:50 +000066// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040067const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080068 InvalidPort = 0xffffffff
69 MaxNumOfGroupHandlerChannels = 256
70
71 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
72 McastFlowOrGroupModify = "McastFlowOrGroupModify"
73 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050074 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010075
76 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053077 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040078)
79
Mahir Gunyela2e68702022-12-07 00:00:42 -080080// DeviceHandler will interact with the OLT device.
Phaneendra Manda4c62c802019-03-06 21:37:49 +053081type DeviceHandler struct {
Akash Kankanala041a2122024-10-16 15:49:22 +053082 EventProxy eventif.EventProxy
83 Client oop.OpenoltClient
84 cm *config.ConfigManager
85 device *voltha.Device
86 cfg *conf.AdapterFlags
87 coreClient *vgrpc.Client
88 childAdapterClients map[string]*vgrpc.Client
89 openOLT *OpenOLT
90 exitChannel chan struct{}
91 transitionMap *TransitionMap
92 clientCon *grpc.ClientConn
93 groupMgr *OpenOltGroupMgr
94 eventMgr *OpenOltEventMgr
95 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070096
97 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053098
Akash Kankanala041a2122024-10-16 15:49:22 +053099 portStats *OpenOltStatisticsMgr
100 metrics *pmmetrics.PmMetrics
101 stopCollector chan bool
102 stopHeartbeatCheck chan bool
103 stopIndications chan bool
104 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
105
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700106 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
107 // if the value is true that means the OnuDiscovery indication
108 // is currently being processed and thus we can ignore concurrent requests
109 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
110 // if we do it means something went wrong and we need to retry
Akash Kankanala041a2122024-10-16 15:49:22 +0530111 discOnus sync.Map
112 onus sync.Map
113 activePorts sync.Map
114 flowMgr []*OpenOltFlowMgr
115 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra491a9c62021-01-06 16:43:07 -0800116
117 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
118 // 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 -0700119 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
120 stopMcastHandlerRoutine []chan bool
121 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000122
Akash Kankanala041a2122024-10-16 15:49:22 +0530123 lockChildAdapterClients sync.RWMutex
124 lockDevice sync.RWMutex
125 perPonOnuIndicationChannelLock sync.Mutex
126
127 totalPonPorts uint32
128 heartbeatSignature uint32
129 isCollectorActive bool
130 isHeartbeatCheckActive bool
131 isReadIndicationRoutineActive bool
132
Gamze Abakac2c32a62021-03-11 11:44:18 +0000133 adapterPreviouslyConnected bool
134 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700135
136 isDeviceDeletionInProgress bool
Nandita Biradar1b590f12024-09-27 10:56:28 +0530137 prevOperStatus common.OperStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700138}
139
Mahir Gunyela2e68702022-12-07 00:00:42 -0800140// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700141type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400142 deviceID string
143 deviceType string
144 serialNumber string
Akash Kankanala041a2122024-10-16 15:49:22 +0530145 proxyDeviceID string
146 adapterEndpoint string
khenaidoo106c61a2021-08-11 18:05:46 -0400147 onuID uint32
148 intfID uint32
khenaidoo106c61a2021-08-11 18:05:46 -0400149 losRaised bool
150 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700151}
152
Mahir Gunyelb0046752021-02-26 13:51:05 -0800153type onuIndicationMsg struct {
154 ctx context.Context
155 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800156}
157
158type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800159 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800160 stopChannel chan struct{}
161}
162
Mahir Gunyela2e68702022-12-07 00:00:42 -0800163// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
164// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
165// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
166// 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 -0800167type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400168 ctx context.Context // Flow/group handler context
khenaidoodc2116e2021-10-19 17:33:19 -0400169 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
170 group *of.OfpGroupEntry // Group message (can be nil or valid group)
171 errChan *chan error // channel to report the mcast Flow/group handling error
Akash Kankanala041a2122024-10-16 15:49:22 +0530172 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
Girish Gowdra491a9c62021-01-06 16:43:07 -0800173}
174
Naga Manjunath7615e552019-10-11 22:35:47 +0530175var pmNames = []string{
176 "rx_bytes",
177 "rx_packets",
178 "rx_mcast_packets",
179 "rx_bcast_packets",
180 "tx_bytes",
181 "tx_packets",
182 "tx_mcast_packets",
183 "tx_bcast_packets",
184}
185
Mahir Gunyela2e68702022-12-07 00:00:42 -0800186// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400187func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700188 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700189 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700190 device.deviceType = deviceTp
191 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700192 device.onuID = onuID
193 device.intfID = intfID
194 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530195 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400196 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700197 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530198}
199
Mahir Gunyela2e68702022-12-07 00:00:42 -0800200// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400201func 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 -0700202 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530203 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800204 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400205 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400206 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700207 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700208 dh.device = cloned
209 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500210 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700211 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000212 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
213 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530214 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 -0500215 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800216 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800217 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400218 dh.childAdapterClients = make(map[string]*vgrpc.Client)
219 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300220 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530221 if dh.kvStore == nil {
222 logger.Error(ctx, "Failed to setup KV store")
223 return nil
224 }
225
Girish Gowdra491a9c62021-01-06 16:43:07 -0800226 // Create a slice of buffered channels for handling concurrent mcast flow/group.
227 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700228 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
229 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800230 for i := range dh.incomingMcastFlowOrGroup {
231 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800232 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800233 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
234 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
235 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
236 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700237 dh.mcastHandlerRoutineActive[i] = true
238 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800239 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530240 // TODO initialize the support classes.
cuilin20187b2a8c32019-03-26 19:52:28 -0700241 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530242}
243
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530244func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
245 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
246 switch storeType {
247 case "etcd":
248 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Abhay Kumar9bcfeb22024-07-12 09:14:25 +0530249 case "redis":
250 return kvstore.NewRedisClient(address, timeout, false)
251 case "redis-sentinel":
252 return kvstore.NewRedisClient(address, timeout, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530253 }
254 return nil, errors.New("unsupported-kv-store")
255}
256
257// SetKVClient sets the KV client and return a kv backend
258func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
259 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
260 if err != nil {
261 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
262 return nil
263 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530264 kvbackend := &db.Backend{
265 Client: kvClient,
266 StoreType: backend,
267 Address: addr,
268 Timeout: rsrcMgr.KvstoreTimeout,
269 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
270
271 return kvbackend
272}
273
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000274// CloseKVClient closes open KV clients
275func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
276 if dh.resourceMgr != nil {
277 for _, rscMgr := range dh.resourceMgr {
278 if rscMgr != nil {
279 rscMgr.CloseKVClient(ctx)
280 }
281 }
282 }
283 if dh.flowMgr != nil {
284 for _, flMgr := range dh.flowMgr {
285 if flMgr != nil {
286 flMgr.CloseKVClient(ctx)
287 }
288 }
289 }
290}
291
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530292// start save the device to the data model
293func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700294 dh.lockDevice.Lock()
295 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000296 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700297 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000298 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530299}
300
khenaidooefff76e2021-12-15 16:51:30 -0500301// Stop stops the device handler
302func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700303 dh.lockDevice.Lock()
304 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000305 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500306 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400307
khenaidooefff76e2021-12-15 16:51:30 -0500308 // Delete (which will stop also) all grpc connections to the child adapters
309 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000310 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530311}
312
ssiddiqui04386ee2021-08-23 21:58:25 +0530313func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
314 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
315 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
316 if pooledIntfID == intfID {
317 return resourceRanges.GetTechnology()
318 }
319 }
320 }
321 return ""
322}
323
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400324func macifyIP(ip net.IP) string {
325 if len(ip) > 0 {
326 oct1 := strconv.FormatInt(int64(ip[12]), 16)
327 oct2 := strconv.FormatInt(int64(ip[13]), 16)
328 oct3 := strconv.FormatInt(int64(ip[14]), 16)
329 oct4 := strconv.FormatInt(int64(ip[15]), 16)
330 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
331 }
332 return ""
333}
334
Neha Sharma96b7bf22020-06-15 10:37:32 +0000335func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400336 var genmac string
337 var addr net.IP
338 var ips []string
339 var err error
340
Neha Sharma96b7bf22020-06-15 10:37:32 +0000341 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400342
343 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000344 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400345
346 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000347 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400348 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000349 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400350 }
351 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000352 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530353 log.Fields{"host": ips[0],
354 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400355 return genmac, nil
356 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000357 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400358 }
359
360 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000361 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530362 log.Fields{"host": host,
363 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400364 return genmac, nil
365}
366
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530367func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700368 slist := strings.Split(mac, ":")
369 result := make([]uint32, len(slist))
370 var err error
371 var tmp int64
372 for index, val := range slist {
373 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
374 return []uint32{1, 2, 3, 4, 5, 6}
375 }
376 result[index] = uint32(tmp)
377 }
378 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530379}
380
Mahir Gunyela2e68702022-12-07 00:00:42 -0800381// 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 -0800382func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800383 switch portType {
384 case voltha.Port_ETHERNET_NNI:
385 return fmt.Sprintf("nni-%d", portNum), nil
386 case voltha.Port_PON_OLT:
387 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700388 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800389
Girish Kumarf26e4882020-03-05 06:49:10 +0000390 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530391}
392
Elia Battiston596406d2022-02-02 12:19:00 +0100393func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
394 if speedMbps == 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530395 // In case it was not set in the indication
396 // and no other value was provided
Elia Battiston596406d2022-02-02 12:19:00 +0100397 speedMbps = defaultPortSpeedMbps
398 }
399
400 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
401 switch speedMbps {
402 case 1000000:
403 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
404 case 100000:
405 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
406 case 40000:
407 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
408 case 10000:
409 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
410 case 1000:
411 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
412 case 100:
413 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
414 case 10:
415 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
416 }
417
418 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
419
420 port := &of.OfpPort{
421 HwAddr: macAddressToUint32Array(macAddress),
422 Config: 0,
423 State: uint32(of.OfpPortState_OFPPS_LIVE),
424 Curr: capacity,
425 Advertised: capacity,
426 Peer: capacity,
Akash Kankanala041a2122024-10-16 15:49:22 +0530427 CurrSpeed: speedMbps * 1000, // kbps
428 MaxSpeed: speedMbps * 1000, // kbps
Elia Battiston596406d2022-02-02 12:19:00 +0100429 }
430
431 return port
432}
433
434func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000435 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700436 if state == "up" {
437 operStatus = voltha.OperStatus_ACTIVE
Akash Kankanala041a2122024-10-16 15:49:22 +0530438 // populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500439 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700440 } else {
441 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500442 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700443 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700444 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400445 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800446 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000447 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400448 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500449
khenaidoo106c61a2021-08-11 18:05:46 -0400450 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400451 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400452 DeviceId: dh.device.Id,
453 Port: portNum,
454 })
455 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000456 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400457 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400458 DeviceId: dh.device.Id,
459 PortType: portType,
460 PortNo: portNum,
461 OperStatus: operStatus})
462 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400463 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
464 "device-id": dh.device.Id,
465 "port-type": portType,
466 "port-number": portNum,
467 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500468 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400469 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500470 }
khenaidoo106c61a2021-08-11 18:05:46 -0400471
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400472 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400473 port = &voltha.Port{
474 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700475 PortNo: portNum,
476 Label: label,
477 Type: portType,
478 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100479 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700480 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000481 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700482 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400483 err = dh.createPortInCore(ctx, port)
484 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000485 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800486 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000487 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400488 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000489 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530490 return nil
491}
492
Kent Hagermane6ff1012020-07-14 15:07:53 -0400493func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400494 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530495 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400496 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
497 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530498 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800499 dh.lockDevice.Lock()
500 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530501 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530502}
503
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700504// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530505// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800506func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000507 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700508 defer func() {
509 dh.lockDevice.Lock()
510 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530511 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700512 dh.lockDevice.Unlock()
513 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700514 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700515 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700516 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700517 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400518
David Bainbridgef5879ca2019-12-13 21:17:54 +0000519 // Create an exponential backoff around re-enabling indications. The
520 // maximum elapsed time for the back off is set to 0 so that we will
521 // continue to retry. The max interval defaults to 1m, but is set
522 // here for code clarity
523 indicationBackoff := backoff.NewExponentialBackOff()
524 indicationBackoff.MaxElapsedTime = 0
525 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700526
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700527 dh.lockDevice.Lock()
528 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530529 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700530 dh.lockDevice.Unlock()
531
Girish Gowdra3f974912020-03-23 20:35:18 -0700532Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700533 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400534 select {
535 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000536 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700537 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400538 default:
539 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100540
541 select {
542 case <-indications.Context().Done():
543 if err != nil {
544 logger.Warnw(ctx, "error-during-enable-indications",
545 log.Fields{"err": err,
546 "device-id": dh.device.Id})
547 }
548
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400549 // Use an exponential back off to prevent getting into a tight loop
550 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100551 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
552 "device-id": dh.device.Id,
553 "duration": duration,
554 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400555 if duration == backoff.Stop {
556 // If we reach a maximum then warn and reset the backoff
557 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100558 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530559 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530560 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400561 indicationBackoff.Reset()
562 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700563
564 // On failure process a backoff timer while watching for stopIndications
565 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700566 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700567 select {
568 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000569 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700570 if !backoffTimer.Stop() {
571 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700572 }
573 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700574 case <-backoffTimer.C:
575 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700576 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700577 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
578 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400579 }
580 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100581 default:
582 if err != nil {
583 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530584 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530585 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100586 // Close the stream, and re-initialize it
587 if err = indications.CloseSend(); err != nil {
588 // Ok to ignore here, because we landed here due to a problem on the stream
589 // In all probability, the closeSend call may fail
590 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
591 log.Fields{"err": err,
592 "device-id": dh.device.Id})
593 }
594 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
595 return err
596 }
597 // once we re-initialized the indication stream, continue to read indications
598 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700599 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100600 // Reset backoff if we have a successful receive
601 indicationBackoff.Reset()
602 // When OLT is admin down, ignore all indications.
603 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
604 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
605 log.Fields{"indication": indication,
606 "device-id": dh.device.Id})
607 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700608 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100609 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530610 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700611 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700612 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700613 // Close the send stream
614 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700615
Girish Gowdra3f974912020-03-23 20:35:18 -0700616 return nil
617}
618
619func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700620 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700621 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
622 if err != nil {
623 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
624 }
625 if indications == nil {
626 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
627 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700628 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700629 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400630}
631
632// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
633func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
634 switch indication.Data.(type) {
635 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
636 return true
637
638 default:
639 return false
640 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700641}
642
David K. Bainbridge794735f2020-02-11 21:01:37 -0800643func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700644 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000645 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530646 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700647 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530648 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000650 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000651 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530652 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000653 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800654 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000655 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800656 }
657 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658}
659
Akash Kankanala041a2122024-10-16 15:49:22 +0530660// nolint: gocyclo,govet
npujarec5762e2020-01-01 14:08:48 +0530661func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700662 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700663 switch indication.Data.(type) {
664 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000665 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
666 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700667 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 -0800668 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400669 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800670 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700671 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000672 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
673 defer span.Finish()
674
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700675 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800676 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100677 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400678 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800679 }
680 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000681 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700682 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000683 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
684 defer span.Finish()
685
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700686 intfOperInd := indication.GetIntfOperInd()
687 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800688 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100689 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400690 _ = 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 -0800691 }
692 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 } else if intfOperInd.GetType() == "pon" {
694 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
695 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800696 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100697 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400698 _ = 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 -0800699 }
700 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000701 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700702 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000703 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530704 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530705 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700706 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000707 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
708 defer span.Finish()
709
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000711 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530712 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800713 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700714 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000715 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
716 defer span.Finish()
717
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700718 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000719 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +0530720 // put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800721 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700722 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000723 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
724 defer span.Finish()
725
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700726 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000727 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 -0800728 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000729 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400730 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800731 }
732 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700733 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000734 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
735 defer span.Finish()
736
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700737 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000738 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700739 "intf-type": pktInd.IntfId,
740 "intf-id": pktInd.IntfId,
741 "gem-port-id": pktInd.GemportId,
742 "port-no": pktInd.PortNo,
743 "device-id": dh.device.Id,
744 })
745
746 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000747 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700748 "intf-type": pktInd.IntfId,
749 "intf-id": pktInd.IntfId,
750 "gem-port-id": pktInd.GemportId,
751 "port-no": pktInd.PortNo,
752 "packet": hex.EncodeToString(pktInd.Pkt),
753 "device-id": dh.device.Id,
754 })
755 }
756
David K. Bainbridge794735f2020-02-11 21:01:37 -0800757 go func() {
758 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400759 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800760 }
761 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700762 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000763 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
764 defer span.Finish()
765
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700766 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700767 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700768 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000769 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
770 defer span.Finish()
771
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700772 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000773 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700774 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000775 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
776 defer span.Finish()
777
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700778 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000779 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
780 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700781 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530782}
783
nikesh.krishnanc8473432023-06-14 12:14:54 +0530784func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
785 onuInd := &oop.OnuIndication{
786 IntfId: intfID,
787 OnuId: onuID,
788 OperState: operState,
789 AdminState: adminState,
790 }
791 indication := &oop.Indication{
792 Data: &oop.Indication_OnuInd{
793 OnuInd: onuInd,
794 },
795 }
796 return indication
797}
798
799func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
800 onuAlarmInd := &oop.OnuAlarmIndication{
801 IntfId: intfID,
802 OnuId: onuID,
803 LosStatus: losStatus,
804 }
805 alarmInd := &oop.AlarmIndication{
806 Data: &oop.AlarmIndication_OnuAlarmInd{
807 OnuAlarmInd: onuAlarmInd,
808 },
809 }
810 return alarmInd
811}
nikesh.krishnanc8473432023-06-14 12:14:54 +0530812
Akash Kankanala041a2122024-10-16 15:49:22 +0530813func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530814 ponlosAlarmInd := &oop.LosIndication{
815 IntfId: intfID,
816 Status: losStatus,
817 }
818 alarmInd := &oop.AlarmIndication{
819 Data: &oop.AlarmIndication_LosInd{
820 LosInd: ponlosAlarmInd,
821 },
822 }
823 return alarmInd
824}
Akash Kankanala041a2122024-10-16 15:49:22 +0530825
nikesh.krishnanc8473432023-06-14 12:14:54 +0530826func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
827 go func() {
828 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
829 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
830 }
831 }()
832
833 raisedTs := time.Now().Unix()
834 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
835}
836
837func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530838 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
839 if err != nil {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530840 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530841 return err
842 }
843 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
nikesh.krishnanc8473432023-06-14 12:14:54 +0530844 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
845 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
846 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
847
848 onuID := onuDeviceFromCore.ProxyAddress.OnuId
849 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
850 if err != nil {
851 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530852 } else {
853 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
854 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
855 switch {
856 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
857 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
858 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
859
860 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
Akash Kankanala041a2122024-10-16 15:49:22 +0530861 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") // check bal cli login notepad
nikesh.krishnanc8473432023-06-14 12:14:54 +0530862 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
863 raisedTs := time.Now().Unix()
864 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
865
866 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
867 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530868 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530869 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530870 return nil
871}
872
873func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
874 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
875 DeviceId: dh.device.Id,
876 PortType: voltha.Port_PON_OLT,
877 })
878 if err != nil {
879 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530880 return err
nikesh.krishnanc8473432023-06-14 12:14:54 +0530881 }
882 for _, portFromCore := range portsFromCore.Items {
883 portNum := portFromCore.GetPortNo()
884 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
885 portOperStatusFromCore := portFromCore.OperStatus
886 portAdminStateFromCore := portFromCore.AdminState
887 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
888 if err != nil {
889 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
890 } else {
891 portLosFromOlt := ponPortFromOlt.GetLos()
892 portStateFromOlt := ponPortFromOlt.GetState()
893 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
894 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
895 "portStateFromOlt": portStateFromOlt.String(),
896 "portOperStatusFromCore": portOperStatusFromCore.String(),
897 "device-id": dh.device.Id,
898 "port": portNum})
899 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
900 raisedTs := time.Now().Unix()
901 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530902 }
903 switch {
904 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
905 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
906 "portStateFromOlt": portStateFromOlt.String(),
907 "portOperStatusFromCore": portOperStatusFromCore.String(),
908 "device-id": dh.device.Id,
909 "port": portNum})
910 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
911 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
912 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
913 "portStateFromOlt": portStateFromOlt.String(),
914 "portOperStatusFromCore": portOperStatusFromCore.String(),
915 "device-id": dh.device.Id,
916 "port": portNum})
917 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
918 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
919 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
920 "device-id": dh.device.Id,
921 "port": portNum})
922 default:
923 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
924 "portStateFromOlt": portStateFromOlt.String(),
925 "portOperStatusFromCore": portOperStatusFromCore.String(),
926 "device-id": dh.device.Id,
927 "port": portNum})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530928 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530929 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530930 }
nikesh.krishnanc8473432023-06-14 12:14:54 +0530931 return nil
932}
933
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530934// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530935func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530936 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +0530937 // Declare deviceStateFilter to be used later
938 var deviceStateFilter *ca.DeviceStateFilter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000939 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530940 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +0530941 if err != nil {
942 return fmt.Errorf("failed to get device from core: %w", err)
943 }
944 logger.Info(ctx, "Device state", log.Fields{
945 "device-id": device.Id,
946 "CurrOperStatus": device.OperStatus,
947 "CurrConnStatus": device.ConnectStatus,
948 })
949 // Perform cleanup if the device's operational status is REBOOTED
950 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
951 // Log the device's operational status if it's REBOOTED
952 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
953 "device-id": device.Id,
954 "OperStatus": device.OperStatus,
955 })
956 dh.lockDevice.RLock()
957 // Stop the read indication only if it the routine is active
958 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
959 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
960 // on next execution of the readIndication routine.
961 if dh.isHeartbeatCheckActive {
962 dh.stopHeartbeatCheck <- true
963 }
964 if dh.isReadIndicationRoutineActive {
965 dh.stopIndications <- true
966 }
967 dh.lockDevice.RUnlock()
Akash Kankanala041a2122024-10-16 15:49:22 +0530968 if err = dh.cleanupDeviceResources(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +0530969 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
970 return fmt.Errorf("cleanup device resources failed: %w", err)
971 }
Akash Kankanala041a2122024-10-16 15:49:22 +0530972 if err = dh.initializeDeviceHandlerModules(ctx); err != nil {
Nandita Biradar1b590f12024-09-27 10:56:28 +0530973 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
974 }
975 go startHeartbeatCheck(ctx, dh)
Nandita Biradar1b590f12024-09-27 10:56:28 +0530976 //dh.lockDevice.RUnlock()
Nandita Biradar1b590f12024-09-27 10:56:28 +0530977 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
978 // Log the device's operational status if it's RECONCILING
979 logger.Info(ctx, "Device is being reconciled", log.Fields{
980 "device-id": device.Id,
981 "OperStatus": device.OperStatus,
982 })
983
984 // Perform reconciliation steps
985 err = dh.reconcileOnus(ctx)
986 if err != nil {
987 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
988 }
989 err = dh.reconcilePonPorts(ctx)
990 if err != nil {
991 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +0530992 }
993 }
Girish Gowdra618fa572021-09-01 17:19:29 -0700994 // instantiate the mcast handler routines.
995 for i := range dh.incomingMcastFlowOrGroup {
996 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
997 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
998 if !dh.mcastHandlerRoutineActive[i] {
999 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1000 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1001 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1002 // for incoming mcast flow/group to be processed serially.
1003 dh.mcastHandlerRoutineActive[i] = true
1004 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1005 }
1006 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301007 // Create DeviceStateFilter with the desired operational and connection statuses
1008 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001009 DeviceId: dh.device.Id,
1010 OperStatus: voltha.OperStatus_ACTIVE,
1011 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301012 }
1013 // Log DeviceStateFilter for debugging purposes
1014 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1015 "DeviceId": deviceStateFilter.DeviceId,
1016 "OperStatus": deviceStateFilter.OperStatus,
1017 "ConnStatus": deviceStateFilter.ConnStatus,
1018 })
1019 // Synchronous call to update device state - this method is run in its own go routine
balaji6299cb23cbe2025-04-14 17:53:10 +05301020 if err = dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001021 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001022 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001023
Akash Kankanala041a2122024-10-16 15:49:22 +05301024 // Clear olt communication failure event
Gamze Abaka07868a52020-12-17 14:19:28 +00001025 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1026 dh.device.OperStatus = voltha.OperStatus_ACTIVE
balaji6299cb23cbe2025-04-14 17:53:10 +05301027
1028 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
1029 if err != nil {
1030 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
1031 }
1032 dh.populateActivePorts(ctx, ports.Items)
1033 if err = dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1034 logger.Error(ctx, "port-status-update-failed", log.Fields{"error": err, "ports": ports})
1035 }
1036
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001037 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001038 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1039
Girish Gowdru0c588b22019-04-23 23:24:56 -04001040 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301041}
1042
1043// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301044func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001045 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001046
khenaidoo106c61a2021-08-11 18:05:46 -04001047 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001048 if err != nil || device == nil {
1049 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001050 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001051 }
1052
1053 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001054
Akash Kankanala041a2122024-10-16 15:49:22 +05301055 // Update the device oper state and connection status
Girish Gowdrud4245152019-05-10 00:47:31 -04001056 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001057 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001058 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001059 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001060
khenaidoodc2116e2021-10-19 17:33:19 -04001061 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001062 DeviceId: cloned.Id,
1063 OperStatus: cloned.OperStatus,
1064 ConnStatus: cloned.ConnectStatus,
1065 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001066 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001067 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001068
Akash Kankanala041a2122024-10-16 15:49:22 +05301069 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001070 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001071 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001072 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001073 }
1074 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001075 // Update onu state as down in onu adapter
1076 onuInd := oop.OnuIndication{}
1077 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001078
1079 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1080 if err != nil {
1081 return err
1082 }
1083 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001084 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001085 DeviceId: onuDevice.Id,
1086 OnuIndication: &onuInd,
1087 })
1088 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001089 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001090 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001091 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001092 "onu-indicator": onuInd,
1093 "device-type": onuDevice.Type,
1094 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
Akash Kankanala041a2122024-10-16 15:49:22 +05301095 // Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001096 } else {
1097 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 -07001098 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001099 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001100 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001101 /* Discovered ONUs entries need to be cleared , since after OLT
1102 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301103 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001104 dh.lockDevice.Unlock()
1105
Neha Sharma96b7bf22020-06-15 10:37:32 +00001106 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001107 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301108}
1109
1110// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301111func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001112 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001113
1114 // if the connection is already available, close the previous connection (olt reboot case)
1115 if dh.clientCon != nil {
1116 if err = dh.clientCon.Close(); err != nil {
1117 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1118 } else {
1119 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1120 }
1121 }
1122
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301123 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +00001124 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001125 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1126 grpc.WithInsecure(),
1127 grpc.WithBlock(),
1128 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001129 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001130 )),
1131 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001132 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001133 )))
1134
1135 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301136 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301137 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001138 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001139 }
Akash Sonif49299a2024-04-25 12:06:37 +05301140 //Setting oper and connection state to RECONCILING and conn state to reachable
1141 cgClient, err := dh.coreClient.GetCoreServiceClient()
1142 if err != nil {
1143 return err
1144 }
1145
1146 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1147 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1148 defer cancel()
1149 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1150 DeviceId: dh.device.Id,
1151 OperStatus: voltha.OperStatus_RECONCILING,
1152 ConnStatus: voltha.ConnectStatus_REACHABLE,
1153 }); err != nil {
1154 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1155 }
1156 // 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
1157 // locally cached copy of the device struct.
1158 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1159 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1160 }
1161
Girish Gowdru0c588b22019-04-23 23:24:56 -04001162 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301163}
1164
1165// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301166func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001167 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301168 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001169 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301170}
1171
1172// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301173func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301174 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001175 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001176
1177 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001178 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301179 if err != nil || device == nil {
1180 /*TODO: needs to handle error scenarios */
1181 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1182 }
1183 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001184 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001185
1186 cloned := proto.Clone(device).(*voltha.Device)
1187 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1188 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1189 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001190
khenaidoodc2116e2021-10-19 17:33:19 -04001191 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001192 DeviceId: cloned.Id,
1193 OperStatus: cloned.OperStatus,
1194 ConnStatus: cloned.ConnectStatus,
1195 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301196 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 -04001197 }
1198
Chaitrashree G S44124192019-08-07 20:21:36 -04001199 // 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 +05301200 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001201 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301202 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001203 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001204 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1205 // all the modules initialized and ready to handle incoming ONUs.
1206
Thomas Lee S985938d2020-05-04 11:40:41 +05301207 err = dh.initializeDeviceHandlerModules(ctx)
1208 if err != nil {
1209 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 -04001210 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001211
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001212 go startHeartbeatCheck(ctx, dh)
1213
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001214 return nil
1215 }
1216
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001217 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301218 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 -04001219 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301220
Neha Sharma96b7bf22020-06-15 10:37:32 +00001221 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001222
1223 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001224 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001225 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001226
1227 go startHeartbeatCheck(ctx, dh)
1228
cuilin20187b2a8c32019-03-26 19:52:28 -07001229 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301230}
1231
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001232func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001233 var err error
1234 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001235
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001236 if dh.flowMgr != nil {
1237 dh.StopAllFlowRoutines(ctx)
1238 }
1239
1240 dh.CloseKVClient(ctx)
1241
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001242 if err != nil {
1243 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1244 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001245 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1246 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +00001247 // +1 is for NNI
1248 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1249 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001250 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001251 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1252 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1253 // There is only one NNI manager since multiple NNI is not supported for now
1254 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001255 // Instantiate resource manager
1256 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 -07001257 return olterrors.ErrResourceManagerInstantiating
1258 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001259 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001260 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1261 // the KV store to manage mcast group data. Provide the first instance (0th index)
1262 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1263 return olterrors.ErrGroupManagerInstantiating
1264 }
yasin saplid0566272021-12-21 09:10:30 +00001265 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001266 // Instantiate flow manager
1267 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05301268 // Continue to check the rest of the ports
Mahir Gunyela2e68702022-12-07 00:00:42 -08001269 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1270 } else {
1271 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001272 }
1273 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001274 /* TODO: Instantiate Alarm , stats , BW managers */
1275 /* Instantiating Event Manager to handle Alarms and KPIs */
1276 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1277
1278 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001279 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001280
1281 return nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001282}
1283
Neha Sharma96b7bf22020-06-15 10:37:32 +00001284func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001285 var err error
1286 var deviceInfo *oop.DeviceInfo
Akash Kankanala041a2122024-10-16 15:49:22 +05301287 var genmac string
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001288
Neha Sharma8f4e4322020-08-06 10:51:53 +00001289 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001290
1291 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001292 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001293 }
1294 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001295 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001296 }
1297
Neha Sharma96b7bf22020-06-15 10:37:32 +00001298 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001299 dh.device.Root = true
1300 dh.device.Vendor = deviceInfo.Vendor
1301 dh.device.Model = deviceInfo.Model
1302 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1303 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1304 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1305
1306 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001307 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001308 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Akash Kankanala041a2122024-10-16 15:49:22 +05301309 genmac, err = generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001310 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001311 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001312 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001313 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001314 dh.device.MacAddress = genmac
1315 } else {
1316 dh.device.MacAddress = deviceInfo.DeviceId
1317 }
1318
1319 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001320 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001321 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001322 }
1323
1324 return deviceInfo, nil
1325}
1326
Neha Sharma96b7bf22020-06-15 10:37:32 +00001327func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001328 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001329
1330 defer func() {
1331 dh.lockDevice.Lock()
1332 dh.isCollectorActive = false
1333 dh.lockDevice.Unlock()
1334 }()
1335
1336 dh.lockDevice.Lock()
1337 dh.isCollectorActive = true
1338 dh.lockDevice.Unlock()
1339
Naga Manjunath7615e552019-10-11 22:35:47 +05301340 for {
1341 select {
1342 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001343 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301344 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001345 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001346
khenaidoo106c61a2021-08-11 18:05:46 -04001347 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001348 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001349 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001350 continue
1351 }
khenaidoo106c61a2021-08-11 18:05:46 -04001352 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301353 // NNI Stats
1354 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001355 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301356 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001357 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001358 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001359 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301360 }
1361 // PON Stats
1362 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001363 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301364 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1365 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001366 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001367 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301368 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001369 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001370
yasin sapli9e4c5092022-02-01 13:52:33 +00001371 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001372 if len(onuGemInfoLst) > 0 {
1373 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001374 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001375 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301376 }
1377 }
1378 }
1379}
1380
Mahir Gunyela2e68702022-12-07 00:00:42 -08001381// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301382func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001383 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001384 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301385 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301386
1387 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001388 cgClient, err := dh.coreClient.GetCoreServiceClient()
1389 if err != nil {
1390 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1391 return
1392 }
1393
1394 // Now, set the initial PM configuration for that device
1395 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001396 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301397 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301398}
1399
Mahir Gunyela2e68702022-12-07 00:00:42 -08001400// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001401func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1402 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001403 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301404 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001405 HwDesc: "open_pon",
1406 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001407 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001408 },
1409 SwitchFeatures: &of.OfpSwitchFeatures{
1410 NBuffers: 256,
1411 NTables: 2,
1412 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1413 of.OfpCapabilities_OFPC_TABLE_STATS |
1414 of.OfpCapabilities_OFPC_PORT_STATS |
1415 of.OfpCapabilities_OFPC_GROUP_STATS),
1416 },
1417 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301418}
1419
khenaidoo106c61a2021-08-11 18:05:46 -04001420// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001421func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001422 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001423 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001424 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001425 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001426 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1427 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()
1428 }
khenaidoo106c61a2021-08-11 18:05:46 -04001429 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001430}
1431
Neha Sharma96b7bf22020-06-15 10:37:32 +00001432func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001433 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 -07001434 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001435 var deviceID string
1436 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001437 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001438
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001439 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001440 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001441 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 -07001442 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1443 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001444
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001445 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301446
1447 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001448 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 -07001449 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001450
khenaidoodc2116e2021-10-19 17:33:19 -04001451 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001452 ParentId: dh.device.Id,
1453 OnuId: omciInd.OnuId,
1454 ParentPortNo: ponPort,
1455 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001456 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301457 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001458 "intf-id": omciInd.IntfId,
1459 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001460 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001461 deviceType = onuDevice.Type
1462 deviceID = onuDevice.Id
1463 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001464 childAdapterEndpoint = onuDevice.AdapterEndpoint
Akash Kankanala041a2122024-10-16 15:49:22 +05301465 // if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001466 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001467 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301468 // found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001469 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 +05301470 deviceType = onuInCache.(*OnuDevice).deviceType
1471 deviceID = onuInCache.(*OnuDevice).deviceID
1472 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001473 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001474 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001475
khenaidoodc2116e2021-10-19 17:33:19 -04001476 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001477 ParentDeviceId: proxyDeviceID,
1478 ChildDeviceId: deviceID,
1479 Message: omciInd.Pkt,
1480 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301481 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001482 "source": dh.openOLT.config.AdapterEndpoint,
1483 "device-type": deviceType,
1484 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001485 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001486 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001487 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001488 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301489}
1490
khenaidoo106c61a2021-08-11 18:05:46 -04001491// //ProcessInterAdapterMessage sends the proxied messages to the target device
1492// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1493// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001494// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001495// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001496// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001497// return dh.handleInterAdapterOmciMsg(ctx, msg)
1498// }
1499// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1500// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001501
kesavandb9f54fd2021-11-25 20:08:04 +05301502// ProxyOmciRequests sends the proxied OMCI message to the target device
1503func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301504 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1505 return status.Error(codes.Unavailable, "OLT unreachable")
1506 }
kesavandb9f54fd2021-11-25 20:08:04 +05301507 if omciMsgs.GetProxyAddress() == nil {
1508 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1509 if err != nil {
1510 return olterrors.NewErrNotFound("onu", log.Fields{
1511 "parent-device-id": dh.device.Id,
1512 "child-device-id": omciMsgs.ChildDeviceId}, err)
1513 }
1514 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1515 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1516 return olterrors.NewErrCommunication("send-failed", log.Fields{
1517 "parent-device-id": dh.device.Id,
1518 "child-device-id": omciMsgs.ChildDeviceId}, err)
1519 }
1520 } else {
1521 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1522 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1523 return olterrors.NewErrCommunication("send-failed", log.Fields{
1524 "parent-device-id": dh.device.Id,
1525 "child-device-id": omciMsgs.ChildDeviceId}, err)
1526 }
1527 }
1528 return nil
1529}
1530
1531func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1532 var intfID uint32
1533 var onuID uint32
1534 var connectStatus common.ConnectStatus_Types
1535 if onuDevice != nil {
1536 intfID = onuDevice.ProxyAddress.GetChannelId()
1537 onuID = onuDevice.ProxyAddress.GetOnuId()
1538 connectStatus = onuDevice.ConnectStatus
1539 } else {
1540 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1541 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1542 connectStatus = omciMsgs.GetConnectStatus()
1543 }
1544 if connectStatus != voltha.ConnectStatus_REACHABLE {
1545 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1546
1547 return olterrors.NewErrCommunication("unreachable", log.Fields{
1548 "intf-id": intfID,
1549 "onu-id": onuID}, nil)
1550 }
1551
1552 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1553 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1554
1555 onuSecOmciMsgList := omciMsgs.GetMessages()
1556
1557 for _, onuSecOmciMsg := range onuSecOmciMsgList {
kesavandb9f54fd2021-11-25 20:08:04 +05301558 var omciMessage *oop.OmciMsg
1559 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1560 hex.Encode(hexPkt, onuSecOmciMsg)
1561 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1562
1563 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1564 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1565 //https://jira.opencord.org/browse/VOL-4604
1566 transid := extractOmciTransactionID(onuSecOmciMsg)
1567 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1568 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1569
1570 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1571 if err != nil {
1572 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1573 "intf-id": intfID,
1574 "onu-id": onuID,
1575 "message": omciMessage}, err)
1576 }
1577 }
1578 return nil
1579}
1580
khenaidoo106c61a2021-08-11 18:05:46 -04001581// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001582func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001583 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 -07001584
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301585 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1586 return status.Error(codes.Unavailable, "OLT unreachable")
1587 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001588 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001589 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001590 if err != nil {
1591 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001592 "parent-device-id": dh.device.Id,
1593 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001594 }
khenaidoo106c61a2021-08-11 18:05:46 -04001595 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1596 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001597 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001598 "parent-device-id": dh.device.Id,
1599 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001600 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001601 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001602 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1603 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001604 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001605 "parent-device-id": dh.device.Id,
1606 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001607 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001608 }
1609 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301610}
1611
khenaidoodc2116e2021-10-19 17:33:19 -04001612func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001613 var intfID uint32
1614 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001615 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001616 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001617 intfID = onuDevice.ProxyAddress.GetChannelId()
1618 onuID = onuDevice.ProxyAddress.GetOnuId()
1619 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001620 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001621 intfID = omciMsg.GetProxyAddress().GetChannelId()
1622 onuID = omciMsg.GetProxyAddress().GetOnuId()
1623 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001624 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001625 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001626 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 -08001627
Thomas Lee S94109f12020-03-03 16:39:29 +05301628 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001629 "intf-id": intfID,
1630 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001631 }
1632
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001633 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1634 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301635 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001636 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001637 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1638 hex.Encode(hexPkt, omciMsg.Message)
1639 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1640
1641 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1642 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1643 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001644 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001645 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001646
Neha Sharma8f4e4322020-08-06 10:51:53 +00001647 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001648 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301649 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001650 "intf-id": intfID,
1651 "onu-id": onuID,
1652 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001653 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001654 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001655}
1656
David K. Bainbridge794735f2020-02-11 21:01:37 -08001657func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301658 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 +00001659 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001660 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001661 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001662 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301663 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301664 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001665 st, _ := status.FromError(err)
1666 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001667 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 -04001668 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301669 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001670 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001671 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001672 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001673 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001675}
1676
Mahir Gunyela2e68702022-12-07 00:00:42 -08001677// getChildDevice function can be used in general to get child device, if not found in cache the function will
1678// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301679func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1680 var InCacheOnuDev *OnuDevice
1681 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1682 if onuInCache.(*OnuDevice).serialNumber == sn {
1683 InCacheOnuDev = onuInCache.(*OnuDevice)
1684 return false
1685 }
1686 return true
1687 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301688 // Got the onu device from cache return
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301689 if InCacheOnuDev != nil {
1690 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1691 return InCacheOnuDev
1692 }
1693 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1694 ParentId: dh.device.Id,
1695 SerialNumber: sn,
1696 ParentPortNo: parentPortNo,
1697 })
Akash Kankanala041a2122024-10-16 15:49:22 +05301698 // No device found in core return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301699 if onuDevice == nil {
1700 return nil
1701 }
1702 onuID := onuDevice.ProxyAddress.OnuId
1703 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1704 onuKey := dh.formOnuKey(intfID, onuID)
1705
1706 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1707 dh.onus.Store(onuKey, onuDev)
1708 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1709 return onuDev
1710}
1711
1712func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001713 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001714 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301715 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001716
Akash Kankanala041a2122024-10-16 15:49:22 +05301717 // CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301718 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1719 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1720 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1721 if onuDev != nil {
1722 var onuGemInfo *rsrcMgr.OnuGemInfo
1723 var err error
1724 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1725 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1726 return false, err
1727 }
1728 if onuGemInfo != nil {
1729 for _, uni := range onuGemInfo.UniPorts {
1730 uniID := plt.UniIDFromPortNum(uni)
1731 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1732 if len(tpIDs) != 0 {
1733 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1734 tpInstExists = true
1735 break
1736 }
1737 }
1738 }
1739 }
1740 return tpInstExists, nil
1741 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301742
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301743 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1744 ParentId: dh.device.Id,
1745 SerialNumber: sn,
1746 ParentPortNo: parentPortNo,
1747 })
1748 if onuDevice != nil {
1749 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1750 return true, nil
1751 }
1752 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1753
1754 return false, nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301755}
1756
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001757// processDiscONULOSClear clears the LOS Alarm if it's needed
1758func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301759 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001760 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301761
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001762 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1763 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1764 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1765 OnuLosRaise event sent for it */
1766 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1767 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1768 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1769 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1770 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1771 "currentIntfId": onuDiscInd.GetIntfId()})
1772 // TODO:: Should we need to ignore raising OnuLosClear event
1773 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301774 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001775 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1776 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1777 alarmInd.LosStatus = statusCheckOff
1778 go func() {
1779 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1780 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1781 }
1782 }()
1783 // stop iterating
1784 return false
1785 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301786 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001787 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301788}
1789
1790func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301791 var error error
1792
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301793 channelID := onuDiscInd.GetIntfId()
1794 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1795
1796 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301797 defer func() {
1798 if error != nil {
1799 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1800 } else {
1801 // once the function completes set the value to false so that
1802 // we know the processing has inProcess.
1803 // Note that this is done after checking if we are already processing
1804 // to avoid changing the value from a different thread
1805 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1806 dh.discOnus.Store(sn, false)
1807 }
1808 }()
1809
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301810 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1811
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301812 tpInstExists, error := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1813 if error != nil {
1814 return error
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301815 }
1816 if tpInstExists {
Akash Kankanala041a2122024-10-16 15:49:22 +05301817 // ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001818 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001819 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001820 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001821 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1822
1823 // if the ONU existed, handle the LOS Alarm
1824 if existing {
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001825 if inProcess.(bool) {
1826 // if we're currently processing the ONU on a different thread, do nothing
1827 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1828 return nil
1829 }
1830 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1831 // then continue processing it
1832 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1833
1834 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001835 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301836 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001837 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001838
1839 // check the ONU is already know to the OLT
1840 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301841 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001842 ParentId: dh.device.Id,
1843 SerialNumber: sn,
1844 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001845
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301846 if error != nil {
1847 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1848 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849 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 -08001850 switch e.Code() {
1851 case codes.Internal:
1852 // this probably means NOT FOUND, so just create a new device
1853 onuDevice = nil
1854 case codes.DeadlineExceeded:
1855 // if the call times out, cleanup and exit
1856 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301857 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1858 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001859 }
1860 }
1861 }
1862
1863 if onuDevice == nil {
1864 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001865 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001866 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001867 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301868 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001869 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001870
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301871 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001872 // if we can't create an ID in resource manager,
1873 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001874 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301875
1876 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001877 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301878 "serial-number": sn}, error)
1879 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001880 }
1881
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301882 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001883 ParentId: dh.device.Id,
1884 ParentPortNo: parentPortNo,
1885 ChannelId: channelID,
1886 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1887 SerialNumber: sn,
1888 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301889 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001890 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001891 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 +05301892
1893 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001894 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301895 "serial-number": sn}, error)
1896 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001897 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301898 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 +05301899 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
1900 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
1901 "onu-id": onuID,
1902 "device-id": dh.device.Id,
1903 "serial-number": sn}, error)
1904 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04001905 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001906 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301907 log.Fields{"onuDevice": onuDevice,
1908 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001909 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301910 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001911 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001912
khenaidoo106c61a2021-08-11 18:05:46 -04001913 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1914 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301915 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04001916 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301917 if error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301918 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
1919 return error
khenaidoo106c61a2021-08-11 18:05:46 -04001920 }
1921
Matteo Scandolo945e4012019-12-12 14:16:11 -08001922 // we can now use the existing ONU Id
1923 onuID = onuDevice.ProxyAddress.OnuId
Akash Kankanala041a2122024-10-16 15:49:22 +05301924 // Insert the ONU into cache to use in OnuIndication.
Mahir Gunyele77977b2019-06-27 05:36:22 -07001925 //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 +00001926 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001927 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301928 "intfId": onuDiscInd.GetIntfId(),
1929 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001930 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001931
khenaidoo106c61a2021-08-11 18:05:46 -04001932 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301933 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001934 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301935 log.Fields{"onu": onuDev,
1936 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001937
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301938 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001939 DeviceId: onuDevice.Id,
1940 ParentDeviceId: dh.device.Id,
1941 OperStatus: common.OperStatus_DISCOVERED,
1942 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301943 }); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301944 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001945 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301946 "serial-number": sn}, error)
1947 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07001948 }
khenaidoo106c61a2021-08-11 18:05:46 -04001949
Neha Sharma96b7bf22020-06-15 10:37:32 +00001950 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301951 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301952 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001953 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301954 "serial-number": sn}, error)
1955 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08001956 }
1957 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001958}
1959
Mahir Gunyelb0046752021-02-26 13:51:05 -08001960func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001961 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001962 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001963 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001964 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001965 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301966 log.Fields{"onuId": onuInd.OnuId,
1967 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301968 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001969 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001970 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001971 errFields := log.Fields{"device-id": dh.device.Id}
1972
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301973 if onuInCache, ok := dh.onus.Load(onuKey); ok {
Akash Kankanala041a2122024-10-16 15:49:22 +05301974 // If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
Mahir Gunyele77977b2019-06-27 05:36:22 -07001975 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001976 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001977 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001978 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05301979 // If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
Mahir Gunyele77977b2019-06-27 05:36:22 -07001980 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001981 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001982 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001983 errFields["onu-id"] = onuInd.OnuId
1984 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001985 }
khenaidoodc2116e2021-10-19 17:33:19 -04001986 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001987 ParentId: dh.device.Id,
1988 SerialNumber: serialNumber,
1989 OnuId: onuInd.OnuId,
1990 ParentPortNo: ponPort,
1991 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001992 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001993
David K. Bainbridge794735f2020-02-11 21:01:37 -08001994 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001995 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001996 }
1997
David K. Bainbridge794735f2020-02-11 21:01:37 -08001998 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001999 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002000 "previousIntfId": onuDevice.ParentPortNo,
2001 "currentIntfId": ponPort})
2002 }
2003
2004 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002005 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302006 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2007 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302008 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002009 }
2010 if !foundInCache {
2011 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
khenaidoo106c61a2021-08-11 18:05:46 -04002012 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 -08002013 }
kesavand7cf3a052020-08-28 12:49:18 +05302014 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002015 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002016 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302017 }
2018 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002019 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002020 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002021 }
2022 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002023}
2024
Neha Sharma96b7bf22020-06-15 10:37:32 +00002025func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002026 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 -07002027 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2028 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2029 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2030 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002031 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002032 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2033 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002034 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002035 onuInd.OperState = "down"
2036 }
2037 }
2038
David K. Bainbridge794735f2020-02-11 21:01:37 -08002039 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002040 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002041 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 -04002042
khenaidoodc2116e2021-10-19 17:33:19 -04002043 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002044 DeviceId: onuDevice.Id,
2045 OnuIndication: onuInd,
2046 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002047 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302048 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002049 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002050 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002051 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002052 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002053 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002054 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002055 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002056 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002057 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002058}
2059
cuilin20187b2a8c32019-03-26 19:52:28 -07002060func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2061 if serialNum != nil {
2062 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002063 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002064 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002065}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002066func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2067 decodedStr, err := hex.DecodeString(serialNum[4:])
2068 if err != nil {
2069 return nil, err
2070 }
2071 return &oop.SerialNumber{
2072 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002073 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002074 }, nil
2075}
cuilin20187b2a8c32019-03-26 19:52:28 -07002076
2077func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002078 if len(vendorSpecific) > 3 {
2079 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2080 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2081 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2082 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2083 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2084 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2085 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2086 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2087 return tmp
2088 }
2089 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002090}
2091
Mahir Gunyela2e68702022-12-07 00:00:42 -08002092// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002093func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302094 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002095}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002096
Mahir Gunyela2e68702022-12-07 00:00:42 -08002097// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002098func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2099 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302100 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002101 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302102 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002103
khenaidoodc2116e2021-10-19 17:33:19 -04002104 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002105 ParentId: dh.device.Id,
2106 OnuId: onuID,
2107 ParentPortNo: parentPort,
2108 })
2109
Girish Gowdru0c588b22019-04-23 23:24:56 -04002110 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002111 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002112 "intf-id": parentPort,
2113 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002114 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002115 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 -08002116 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302117}
2118
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002119// SendPacketInToCore sends packet-in to core
2120// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2121// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002122func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002123 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002124 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002125 "port": logicalPort,
2126 "packet": hex.EncodeToString(packetPayload),
2127 "device-id": dh.device.Id,
2128 })
2129 }
khenaidoo106c61a2021-08-11 18:05:46 -04002130
khenaidoodc2116e2021-10-19 17:33:19 -04002131 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002132 DeviceId: dh.device.Id,
2133 Port: logicalPort,
2134 Packet: packetPayload,
2135 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302136 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002137 "source": "adapter",
2138 "destination": "core",
2139 "device-id": dh.device.Id,
2140 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002141 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002142 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002143 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002144 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002145 "packet": hex.EncodeToString(packetPayload),
2146 "device-id": dh.device.Id,
2147 })
2148 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002149 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002150}
2151
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002152// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002153func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002154 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002155
2156 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2157 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002158 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002159 }
2160
Kent Hagermane6ff1012020-07-14 15:07:53 -04002161 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002162 metrics := dh.metrics.GetSubscriberMetrics()
2163 for _, m := range pmConfigs.Metrics {
2164 metrics[m.Name].Enabled = m.Enabled
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002165 }
2166 }
2167}
2168
khenaidoodc2116e2021-10-19 17:33:19 -04002169func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002170 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002171 var errorsList []error
2172
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002173 if dh.getDeviceDeletionInProgressFlag() {
2174 // The device itself is going to be reset as part of deletion. So nothing to be done.
2175 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2176 return nil
2177 }
2178
Girish Gowdru0c588b22019-04-23 23:24:56 -04002179 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002180 for _, flow := range flows.ToRemove.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302181 intfID := dh.getIntfIDFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002182
Neha Sharma96b7bf22020-06-15 10:37:32 +00002183 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302184 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002185 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302186 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002187 if flow_utils.HasGroup(flow) {
2188 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2189 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002190 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2191 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2192 } else {
2193 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2194 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002195 }
Girish Gowdracefae192020-03-19 18:14:10 -07002196 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002197 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
Akash Kankanala041a2122024-10-16 15:49:22 +05302198 // The flow we want to remove is not there, there is no need to throw an error
Elia Battiston2aaf4342022-02-07 15:16:38 +01002199 logger.Warnw(ctx, "flow-to-remove-not-found",
2200 log.Fields{
2201 "ponIf": intfID,
2202 "flowToRemove": flow,
2203 "error": err,
2204 })
2205 } else {
2206 errorsList = append(errorsList, err)
2207 }
Girish Gowdracefae192020-03-19 18:14:10 -07002208 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002209 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302210
2211 for _, flow := range flows.ToAdd.Items {
Akash Kankanala041a2122024-10-16 15:49:22 +05302212 intfID := dh.getIntfIDFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002213 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302214 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002215 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302216 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002217 if flow_utils.HasGroup(flow) {
2218 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2219 } else {
yasin saplid0566272021-12-21 09:10:30 +00002220 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002221 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2222 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2223 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2224 } else {
yasin saplid0566272021-12-21 09:10:30 +00002225 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002226 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002227 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002228 if err != nil {
2229 errorsList = append(errorsList, err)
2230 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302231 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002232 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002233
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002234 return errorsList
2235}
2236
2237func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2238 var err error
2239 var errorsList []error
2240
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002241 if dh.getDeviceDeletionInProgressFlag() {
2242 // The device itself is going to be reset as part of deletion. So nothing to be done.
2243 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2244 return nil
2245 }
2246
Girish Gowdracefae192020-03-19 18:14:10 -07002247 // 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 +00002248 if groups != nil {
2249 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002250 // err = dh.groupMgr.AddGroup(ctx, group)
2251 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002252 if err != nil {
2253 errorsList = append(errorsList, err)
2254 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002255 }
2256 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002257 // err = dh.groupMgr.ModifyGroup(ctx, group)
2258 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002259 if err != nil {
2260 errorsList = append(errorsList, err)
2261 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002262 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002263 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002264 // err = dh.groupMgr.DeleteGroup(ctx, group)
2265 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002266 if err != nil {
2267 errorsList = append(errorsList, err)
2268 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002269 }
2270 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002271
2272 return errorsList
2273}
2274
Mahir Gunyela2e68702022-12-07 00:00:42 -08002275// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002276func (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 -07002277 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002278
2279 if dh.getDeviceDeletionInProgressFlag() {
2280 // The device itself is going to be reset as part of deletion. So nothing to be done.
2281 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2282 return nil
2283 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302284 if dh.transitionMap.currentDeviceState != deviceStateUp {
2285 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2286 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2287 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002288 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2289 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2290 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002291 if len(errorsList) > 0 {
2292 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2293 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002294 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002295 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302296}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002297
Mahir Gunyela2e68702022-12-07 00:00:42 -08002298// DisableDevice disables the given device
2299// It marks the following for the given device:
2300// Device-Handler Admin-State : down
2301// Device Port-State: UNKNOWN
2302// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002303func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002304 /* On device disable ,admin state update has to be done prior sending request to agent since
2305 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002306 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002307 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002308 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002309 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002310 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002311 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002312 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002313 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002314 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002315 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302316
2317 dh.discOnus = sync.Map{}
2318 dh.onus = sync.Map{}
2319
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002320 dh.lockDevice.RLock()
Akash Kankanala041a2122024-10-16 15:49:22 +05302321 // stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002322 if dh.isCollectorActive {
2323 dh.stopCollector <- true
2324 }
2325 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302326
Neha Sharma96b7bf22020-06-15 10:37:32 +00002327 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002328 cloned := proto.Clone(device).(*voltha.Device)
Akash Kankanala041a2122024-10-16 15:49:22 +05302329 // Update device Admin state
Thomas Lee S985938d2020-05-04 11:40:41 +05302330 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002331
kdarapu1afeceb2020-02-12 01:38:09 -05002332 // 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 -04002333 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002334 DeviceId: cloned.Id,
2335 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2336 OperStatus: voltha.OperStatus_UNKNOWN,
2337 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002338 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002339 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002340 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002341 return nil
2342}
2343
Neha Sharma96b7bf22020-06-15 10:37:32 +00002344func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002345 // Update onu state as unreachable in onu adapter
2346 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302347 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002348
Akash Kankanala041a2122024-10-16 15:49:22 +05302349 // get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002350 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002351 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002352 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 -04002353 }
2354 if onuDevices != nil {
2355 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002356 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002357 DeviceId: onuDevice.Id,
2358 OnuIndication: &onuInd,
2359 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002360 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002361 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002362 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002363 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002364 }
2365 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002366}
2367
Mahir Gunyela2e68702022-12-07 00:00:42 -08002368// ReenableDevice re-enables the olt device after disable
2369// It marks the following for the given device:
2370// Device-Handler Admin-State : up
2371// Device Port-State: ACTIVE
2372// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002373func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302374 if dh.Client != nil {
2375 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2376 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2377 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2378 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302379 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302380 } else {
2381 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 +05302382 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002383 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002384
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002385 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002386 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002387 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002388 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002389 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2390 } else {
2391 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2392 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2393 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002394 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002395 if retError == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302396 // Update the device oper status as ACTIVE
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002397 device.OperStatus = voltha.OperStatus_ACTIVE
2398 } else {
Akash Kankanala041a2122024-10-16 15:49:22 +05302399 // Update the device oper status as FAILED
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002400 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002401 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002402 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002403
khenaidoodc2116e2021-10-19 17:33:19 -04002404 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002405 DeviceId: device.Id,
2406 OperStatus: device.OperStatus,
2407 ConnStatus: device.ConnectStatus,
2408 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302409 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002410 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002411 "connect-status": device.ConnectStatus,
2412 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002413 }
kesavand39e0aa32020-01-28 20:58:50 -05002414
Neha Sharma96b7bf22020-06-15 10:37:32 +00002415 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002416
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002417 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002418}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002419
npujarec5762e2020-01-01 14:08:48 +05302420func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002421 var uniID uint32
2422 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002423 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302424 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002425 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002426 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002427 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002428 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2429 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2430 } else {
2431 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2432 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002433 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002434 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002435 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002436 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002437 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002438 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002439 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002440 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002441 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002442 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002443 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002444 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002445 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002446 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002447 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002448 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302449 }
yasin saplibddc2d72022-02-08 13:10:17 +00002450 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2451 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002452 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002453 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302454 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002455 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002456 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002457 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 -03002458 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002459 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002460 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002461 if len(errs) > 0 {
2462 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2463 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2464 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002465 return nil
2466}
2467
Devmalya Paul495b94a2019-08-27 19:42:00 -04002468// 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 +05302469func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002470 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002471 /* Clear the KV store data associated with the all the UNI ports
2472 This clears up flow data and also resource map data for various
2473 other pon resources like alloc_id and gemport_id
2474 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002475
2476 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002477 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002478
Himani Chawla49a5d562020-11-25 11:53:44 +05302479 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002480 // Stop the Stats collector
2481 if dh.isCollectorActive {
2482 dh.stopCollector <- true
2483 }
2484 // stop the heartbeat check routine
2485 if dh.isHeartbeatCheckActive {
2486 dh.stopHeartbeatCheck <- true
2487 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302488 // Stop the read indication only if it the routine is active
2489 if dh.isReadIndicationRoutineActive {
2490 dh.stopIndications <- true
2491 }
2492 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302493
2494 err := dh.cleanupDeviceResources(ctx)
2495 if err != nil {
2496 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2497 } else {
2498 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2499 }
2500
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002501 dh.removeOnuIndicationChannels(ctx)
Akash Kankanala041a2122024-10-16 15:49:22 +05302502 // Reset the state
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002503 if dh.Client != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302504 if _, err = dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002505 go func() {
2506 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
Akash Kankanala041a2122024-10-16 15:49:22 +05302507 if err1 := dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err1 != nil {
2508 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err1})
Gustavo Silva41af9122022-10-11 11:05:13 -03002509 }
2510 }()
2511 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002512 }
2513 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002514 // There is no need to update the core about operation status and connection status of the OLT.
2515 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2516 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2517 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002518
khenaidoo7eb2d672021-10-22 19:08:50 -04002519 // Stop the adapter grpc clients for that parent device
2520 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002521 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002522}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002523
2524// StopAllFlowRoutines stops all flow routines
2525func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2526 var wg sync.WaitGroup
2527 wg.Add(1) // for the mcast routine below to finish
2528 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2529 for _, flMgr := range dh.flowMgr {
2530 if flMgr != nil {
2531 wg.Add(1) // for the flow handler routine below to finish
2532 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2533 }
2534 }
2535 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2536 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2537 } else {
2538 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2539 }
2540}
2541
Gustavo Silva41af9122022-10-11 11:05:13 -03002542func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2543 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002544 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302545 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002546 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002547 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002548 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002549 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002550 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2551 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302552 }
2553 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002554 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2555 errs = append(errs, err)
2556 }
2557 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2558 errs = append(errs, err)
2559 }
2560 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2561 errs = append(errs, err)
2562 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002563 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002564 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002565 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002566 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002567 }
2568 // Clean up NNI manager's data
2569 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2570 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002571 }
A R Karthick1f85b802019-10-11 05:06:05 +00002572
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002573 dh.CloseKVClient(ctx)
2574
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002575 // Take one final sweep at cleaning up KV store for the OLT device
2576 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002577 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2578 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002579 }
2580
Devmalya Paul495b94a2019-08-27 19:42:00 -04002581 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302582 dh.onus.Range(func(key interface{}, value interface{}) bool {
2583 dh.onus.Delete(key)
2584 return true
2585 })
2586
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002587 /*Delete discovered ONU map for the device*/
2588 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2589 dh.discOnus.Delete(key)
2590 return true
2591 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002592 if len(errs) > 0 {
2593 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2594 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2595 }
2596 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002597}
2598
Mahir Gunyela2e68702022-12-07 00:00:42 -08002599// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002600func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302601 if dh.Client != nil {
2602 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2603 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2604 }
2605 } else {
2606 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 -04002607 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302608
Neha Sharma96b7bf22020-06-15 10:37:32 +00002609 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002610 return nil
2611}
2612
David K. Bainbridge794735f2020-02-11 21:01:37 -08002613func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002614 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002615 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002616 "packet-indication": *packetIn,
2617 "device-id": dh.device.Id,
2618 "packet": hex.EncodeToString(packetIn.Pkt),
2619 })
2620 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002621 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2622 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2623 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002624 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002625 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002626 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002627 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002628 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002629 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002630 "logical-port-num": logicalPortNum,
2631 "device-id": dh.device.Id,
2632 "packet": hex.EncodeToString(packetIn.Pkt),
2633 })
2634 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002635
khenaidoodc2116e2021-10-19 17:33:19 -04002636 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002637 DeviceId: dh.device.Id,
2638 Port: logicalPortNum,
2639 Packet: packetIn.Pkt,
2640 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302641 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002642 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302643 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002644 "device-id": dh.device.Id,
2645 "packet": hex.EncodeToString(packetIn.Pkt),
2646 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002647 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002648
Matteo Scandolo92186242020-06-12 10:54:18 -07002649 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002650 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002651 "packet": hex.EncodeToString(packetIn.Pkt),
2652 "device-id": dh.device.Id,
2653 })
2654 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002655 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002656}
2657
Mahir Gunyela2e68702022-12-07 00:00:42 -08002658// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2659func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2660 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2661 if err != nil {
2662 return olterrors.NewErrInvalidValue(log.Fields{
2663 "egress-nni-port": egressPortNo,
2664 "device-id": dh.device.Id,
2665 }, err)
2666 }
2667 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2668
2669 if logger.V(log.DebugLevel) {
2670 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2671 "uplink-pkt": uplinkPkt,
2672 "packet": hex.EncodeToString(packet.Data),
2673 "device-id": dh.device.Id,
2674 })
2675 }
2676
2677 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2678 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2679 "packet": hex.EncodeToString(packet.Data),
2680 "device-id": dh.device.Id,
2681 }, err)
2682 }
2683 return nil
2684}
2685
2686// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2687func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2688 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2689 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2690 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2691 // Do not packet-out lldp packets on uni port.
2692 // ONOS has no clue about uni/nni ports, it just packets out on all
2693 // available ports on the Logical Switch. It should not be interested
2694 // in the UNI links.
2695 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2696 "device-id": dh.device.Id,
2697 })
2698 return nil
2699 }
2700 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2701 if innerEthType == 0x8100 {
2702 // q-in-q 802.1ad or 802.1q double tagged packet.
2703 // slice out the outer tag.
2704 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2705 if logger.V(log.DebugLevel) {
2706 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2707 "packet-data": hex.EncodeToString(packet.Data),
2708 "device-id": dh.device.Id,
2709 })
2710 }
2711 }
2712 }
2713 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2714 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2715 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2716 var gemPortID uint32
2717 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2718 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2719 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2720 }
2721 if err != nil {
2722 // In this case the openolt agent will receive the gemPortID as 0.
2723 // The agent tries to retrieve the gemPortID in this case.
2724 // This may not always succeed at the agent and packetOut may fail.
2725 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2726 "intf-id": intfID,
2727 "onu-id": onuID,
2728 "uni-id": uniID,
2729 "packet": hex.EncodeToString(packet.Data),
2730 "device-id": dh.device.Id,
2731 "error": err,
2732 })
2733 }
2734
2735 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2736 if logger.V(log.DebugLevel) {
2737 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2738 "egress-port-no": egressPortNo,
2739 "intf-id": intfID,
2740 "onu-id": onuID,
2741 "uni-id": uniID,
2742 "gem-port-id": gemPortID,
2743 "packet": hex.EncodeToString(packet.Data),
2744 "device-id": dh.device.Id,
2745 })
2746 }
2747
2748 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2749 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2750 "source": "adapter",
2751 "destination": "onu",
2752 "egress-port-number": egressPortNo,
2753 "intf-id": intfID,
2754 "oni-id": onuID,
2755 "uni-id": uniID,
2756 "gem-port-id": gemPortID,
2757 "packet": hex.EncodeToString(packet.Data),
2758 "device-id": dh.device.Id,
2759 }, err)
2760 }
2761 return nil
2762}
2763
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002764// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002765func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002766 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002767 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002768 "device-id": dh.device.Id,
2769 "egress-port-no": egressPortNo,
2770 "pkt-length": len(packet.Data),
2771 "packet": hex.EncodeToString(packet.Data),
2772 })
2773 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002774
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002775 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002776 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002777 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002778 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002779 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002780 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002781 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002782 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302783 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002784 "egressPortType": egressPortType,
2785 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302786 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002787 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002788 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002789 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002790}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002791
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002792func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2793 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002794}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302795
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002796func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002797 defer func() {
2798 dh.lockDevice.Lock()
2799 dh.isHeartbeatCheckActive = false
2800 dh.lockDevice.Unlock()
2801 }()
2802
2803 dh.lockDevice.Lock()
2804 dh.isHeartbeatCheckActive = true
2805 dh.lockDevice.Unlock()
2806
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302807 // start the heartbeat check towards the OLT.
2808 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302809 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302810
2811 for {
2812 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2813 select {
2814 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002815 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002816 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002817 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302818 if timerCheck == nil {
2819 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002820 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302821 }
2822 } else {
2823 if timerCheck != nil {
2824 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002825 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302826 }
2827 timerCheck = nil
2828 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302829 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2830 if dh.heartbeatSignature == 0 {
2831 // First time the signature will be 0, update the signture to DB when not found.
2832 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2833 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2834 }
2835 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2836
2837 dh.lockDevice.RLock()
2838 // Stop the read indication only if it the routine is active
2839 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2840 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2841 // on next execution of the readIndication routine.
2842 if !dh.isReadIndicationRoutineActive {
2843 // Start reading indications
2844 go func() {
2845 if err = dh.readIndications(ctx); err != nil {
2846 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2847 }
2848 }()
2849 }
2850 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302851 } else {
2852 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2853 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2854 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2855 go dh.updateStateRebooted(ctx)
2856 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302857 }
2858 cancel()
2859 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002860 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302861 return
2862 }
2863 }
2864}
2865
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002866func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002867 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002868 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002869 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2870 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2871 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2872 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2873 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002874 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002875 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2876 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002877 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302878
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302879 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002880 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002881 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002882 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002883 DeviceId: dh.device.Id,
2884 OperStatus: voltha.OperStatus_UNKNOWN,
2885 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2886 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002887 _ = 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 -04002888 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302889 /*
2890 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2891 DeviceId: dh.device.Id,
2892 PortTypeFilter: 0,
2893 OperStatus: voltha.OperStatus_UNKNOWN,
2894 }); err != nil {
2895 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2896 }
2897 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002898
Akash Kankanala041a2122024-10-16 15:49:22 +05302899 // raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002900 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002901 cloned := proto.Clone(device).(*voltha.Device)
2902 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2903 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2904 dh.device = cloned // update local copy of the device
2905 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002906
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002907 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002908 // Stop the Stats collector
2909 if dh.isCollectorActive {
2910 dh.stopCollector <- true
2911 }
2912 // stop the heartbeat check routine
2913 if dh.isHeartbeatCheckActive {
2914 dh.stopHeartbeatCheck <- true
2915 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002916 // Stop the read indication only if it the routine is active
2917 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2918 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2919 // on next execution of the readIndication routine.
2920 if dh.isReadIndicationRoutineActive {
2921 dh.stopIndications <- true
2922 }
2923 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002924 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302925 }
2926}
kesavand39e0aa32020-01-28 20:58:50 -05002927
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302928func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2929 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2930 if err != nil || device == nil {
2931 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2932 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2933 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2934 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2935 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2936 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2937 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2938 return
2939 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302940 // Starting the cleanup process
Mahir Gunyel701df862023-09-07 16:16:04 -07002941 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302942
2943 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2944 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
bseenivad1c984b2025-01-09 12:54:44 +05302945 // First, stop the read indication and heartbeat check routines to prevent any delay
2946 // in cleanup, which could cause the heartbeat routine to restart the read indication.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302947 dh.lockDevice.RLock()
2948 // Stop the read indication only if it the routine is active
2949 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2950 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2951 // on next execution of the readIndication routine.
2952 if dh.isReadIndicationRoutineActive {
2953 dh.stopIndications <- true
2954 }
2955 dh.lockDevice.RUnlock()
2956
bseenivad1c984b2025-01-09 12:54:44 +05302957 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2958 DeviceId: dh.device.Id,
2959 OperStatus: voltha.OperStatus_REBOOTED,
2960 ConnStatus: voltha.ConnectStatus_REACHABLE,
2961 }); err != nil {
2962 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2963 }
2964
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302965 //raise olt communication failure event
2966 raisedTs := time.Now().Unix()
2967 cloned := proto.Clone(device).(*voltha.Device)
2968 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2969 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2970 dh.device = cloned // update local copy of the device
2971 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2972
Gustavo Silva41af9122022-10-11 11:05:13 -03002973 if err := dh.cleanupDeviceResources(ctx); err != nil {
2974 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
2975 } else {
2976 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2977 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002978
2979 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302980 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002981 if dh.isCollectorActive {
2982 dh.stopCollector <- true
2983 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302984 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002985 if dh.isHeartbeatCheckActive {
2986 dh.stopHeartbeatCheck <- true
2987 }
2988 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302989
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002990 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302991
Akash Kankanala041a2122024-10-16 15:49:22 +05302992 // reset adapter reconcile flag
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302993 dh.adapterPreviouslyConnected = false
2994 for {
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302995 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2996 if err != nil || childDevices == nil {
2997 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2998 continue
2999 }
3000 if len(childDevices.Items) == 0 {
3001 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3002 break
3003 } else {
3004 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3005 time.Sleep(5 * time.Second)
3006 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303007 }
Akash Kankanala041a2122024-10-16 15:49:22 +05303008 // Cleanup completed , reset the flag
Mahir Gunyel701df862023-09-07 16:16:04 -07003009 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303010 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3011 dh.transitionMap.Handle(ctx, DeviceInit)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303012}
3013
kesavand39e0aa32020-01-28 20:58:50 -05003014// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003015func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3016 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3017 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003018}
3019
3020// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003021func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3022 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3023 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003024}
3025
Mahir Gunyela2e68702022-12-07 00:00:42 -08003026// 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 +00003027func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3028 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003029 if port.GetType() == voltha.Port_ETHERNET_NNI {
3030 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303032 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303033 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003034 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003035 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003036 }
3037 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003038 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003039 ponIntf := &oop.Interface{IntfId: ponID}
3040 var operStatus voltha.OperStatus_Types
3041 if enablePort {
3042 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303043 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003044
3045 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303046 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003047 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003048 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003049 }
3050 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003051 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003052 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003053 } else {
3054 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303055 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003056 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303057 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003058 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003059 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003060 }
3061 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003062 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003064 }
khenaidoodc2116e2021-10-19 17:33:19 -04003065 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003066 DeviceId: dh.device.Id,
3067 PortType: voltha.Port_PON_OLT,
3068 PortNo: port.PortNo,
3069 OperStatus: operStatus,
3070 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303071 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303072 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003073 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003074 }
3075 return nil
3076}
3077
Mahir Gunyela2e68702022-12-07 00:00:42 -08003078// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003079func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003080 // Disable the port and update the oper_port_status to core
3081 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003082 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003083 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303085 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303086 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003087 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003088 }
3089 }
3090 }
3091 return nil
3092}
3093
Mahir Gunyela2e68702022-12-07 00:00:42 -08003094// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003095func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3096 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3097 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003098 if port.Type == voltha.Port_ETHERNET_NNI {
3099 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003100 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003101 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003102 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003103 }
3104 }
3105 if port.Type == voltha.Port_PON_OLT {
3106 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003107 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003108 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003109 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003110 }
3111 }
3112 }
3113}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003114
3115// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003116func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003117 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003118 if dh.getDeviceDeletionInProgressFlag() {
3119 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3120 // will reboot, so everything will be reset on the pOLT too.
3121 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3122 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3123 return nil
3124 }
Sridhar Ravindra92c9b0d2025-01-16 00:15:54 +05303125
3126 if dh.transitionMap.currentDeviceState != deviceStateUp {
3127 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})
3128 return fmt.Errorf("device-is-not-up--not-handling-child-device-lost")
3129 }
3130
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003131 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003132 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003133
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003134 var sn *oop.SerialNumber
3135 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003136 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303137 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003138 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303139 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003140 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003141 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003142
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003143 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Akash Kankanala041a2122024-10-16 15:49:22 +05303144 // clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003145 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003146 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3147 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3148 "device-id": dh.device.Id,
3149 "intf-id": intfID,
3150 "onuID": onuID,
3151 "err": err})
3152 } else {
3153 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003154 // Delete flows from device before schedulers and queue
3155 // Clear flowids for gem cache.
3156 removedFlows := []uint64{}
3157 for _, gem := range onuGem.GemPorts {
3158 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3159 for _, flowID := range flowIDs {
Akash Kankanala041a2122024-10-16 15:49:22 +05303160 // multiple gem port can have the same flow id
3161 // it is better to send only one flowRemove request to the agent
yasin saplie87d4bd2021-12-06 09:04:03 +00003162 var alreadyRemoved bool
3163 for _, removedFlowID := range removedFlows {
3164 if removedFlowID == flowID {
3165 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3166 alreadyRemoved = true
3167 break
3168 }
3169 }
3170 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003171 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003172 removedFlows = appendUnique64bit(removedFlows, flowID)
3173 }
3174 }
3175 }
3176 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3177 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003178 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3179 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3180 "device-id": dh.device.Id,
3181 "onu-device": onu,
3182 "err": err})
3183 }
yasin saplibddc2d72022-02-08 13:10:17 +00003184 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003185 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3186 "intf-id": intfID,
3187 "onu-device": onu,
3188 "onu-gem": onuGem,
3189 "err": err})
Akash Kankanala041a2122024-10-16 15:49:22 +05303190 // Not returning error on cleanup.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003191 }
3192 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003193 }
yasin saplibddc2d72022-02-08 13:10:17 +00003194 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003195 dh.onus.Delete(onuKey)
3196 dh.discOnus.Delete(onuSn)
3197
3198 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003199 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303200 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303201 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003202 "onu-id": onuID}, err).Log()
3203 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003204
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003205 return nil
3206}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003207func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3208 flow := &oop.Flow{FlowId: flowID}
3209 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3210 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3211 "device-id": dh.device.Id})
3212 } else {
3213 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3214 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3215 "device-id": dh.device.Id,
3216 "err": err})
3217 }
3218 }
3219}
Girish Gowdracefae192020-03-19 18:14:10 -07003220
3221func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003222 for _, field := range flow_utils.GetOfbFields(flow) {
3223 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003224 return field.GetPort()
3225 }
3226 }
3227 return InvalidPort
3228}
3229
3230func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003231 for _, action := range flow_utils.GetActions(flow) {
3232 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003233 if out := action.GetOutput(); out != nil {
3234 return out.GetPort()
3235 }
3236 }
3237 }
3238 return InvalidPort
3239}
3240
Girish Gowdracefae192020-03-19 18:14:10 -07003241func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3242 inPort := getInPortFromFlow(flow)
3243 outPort := getOutPortFromFlow(flow)
3244
3245 if inPort == InvalidPort || outPort == InvalidPort {
3246 return inPort, outPort
3247 }
3248
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003249 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003250 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003251 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003252 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003253 return uniPort, outPort
3254 }
3255 }
3256 } else {
3257 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003258 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003259 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003260 return inPort, uniPort
3261 }
3262 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003263 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003264 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003265 return uniPort, outPort
3266 }
3267 }
3268 }
3269
3270 return InvalidPort, InvalidPort
3271}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003272
3273func extractOmciTransactionID(omciPkt []byte) uint16 {
3274 if len(omciPkt) > 3 {
3275 d := omciPkt[0:2]
3276 transid := binary.BigEndian.Uint16(d)
3277 return transid
3278 }
3279 return 0
3280}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003281
3282// StoreOnuDevice stores the onu parameters to the local cache.
3283func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3284 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3285 dh.onus.Store(onuKey, onuDevice)
3286}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003287
khenaidoodc2116e2021-10-19 17:33:19 -04003288func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003289 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003290 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003291 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003292 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003293 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003294 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003295 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003296 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3297 return nil, err
3298 }
3299 ID = device.ProxyAddress.GetOnuId()
3300 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3301 valueparam.Onu = &Onu
3302 valueparam.Value = value
3303
3304 // This API is unsupported until agent patch is added
3305 resp.Unsupported = uint32(value)
3306 _ = ctx
3307
3308 // Uncomment this code once agent changes are complete and tests
3309 /*
3310 resp, err = dh.Client.GetValue(ctx, valueparam)
3311 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003312 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003313 return nil, err
3314 }
3315 */
3316
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003317 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 -08003318 return resp, nil
3319}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003320
Akash Kankanala041a2122024-10-16 15:49:22 +05303321func (dh *DeviceHandler) getIntfIDFromFlow(flow *of.OfpFlowStats) uint32 {
yasin saplid0566272021-12-21 09:10:30 +00003322 // Default to NNI
3323 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003324 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003325 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003326 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003327 }
3328 return intfID
3329}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003330
Akash Kankanala041a2122024-10-16 15:49:22 +05303331func (dh *DeviceHandler) getOnuIndicationChannel(intfID uint32) chan onuIndicationMsg {
Mahir Gunyelb0046752021-02-26 13:51:05 -08003332 dh.perPonOnuIndicationChannelLock.Lock()
3333 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3334 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003335 return ch.indicationChannel
3336 }
3337 channels := onuIndicationChannels{
Akash Kankanala041a2122024-10-16 15:49:22 +05303338 // We create a buffered channel here to avoid calling function to be blocked
3339 // in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003340 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003341 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003342 stopChannel: make(chan struct{}),
3343 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003344 dh.perPonOnuIndicationChannel[intfID] = channels
3345 dh.perPonOnuIndicationChannelLock.Unlock()
3346 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003347 return channels.indicationChannel
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003348}
3349
Mahir Gunyelb0046752021-02-26 13:51:05 -08003350func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3351 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3352 dh.perPonOnuIndicationChannelLock.Lock()
3353 defer dh.perPonOnuIndicationChannelLock.Unlock()
3354 for _, v := range dh.perPonOnuIndicationChannel {
3355 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003356 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003357 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003358}
3359
Mahir Gunyelb0046752021-02-26 13:51:05 -08003360func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3361 ind := onuIndicationMsg{
3362 ctx: ctx,
3363 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003364 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003365 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003366 // Send the onuIndication on the ONU channel
Akash Kankanala041a2122024-10-16 15:49:22 +05303367 dh.getOnuIndicationChannel(intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003368}
3369
Mahir Gunyelb0046752021-02-26 13:51:05 -08003370func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003371 for {
3372 select {
3373 // process one indication per onu, before proceeding to the next one
3374 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003375 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003376 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003377 "ind": indication})
3378 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003379 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003380 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003381 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3382 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003383 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003384 }
3385 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003386 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003387 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3388 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003389 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003390 }
3391 }
3392 case <-onuChannels.stopChannel:
3393 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3394 close(onuChannels.indicationChannel)
3395 return
3396 }
3397 }
3398}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003399
3400// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3401// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003402func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003403 if dh.getDeviceDeletionInProgressFlag() {
3404 // The device itself is going to be reset as part of deletion. So nothing to be done.
3405 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3406 return nil
3407 }
3408
Girish Gowdra491a9c62021-01-06 16:43:07 -08003409 // Step1 : Fill McastFlowOrGroupControlBlock
3410 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3411 // Step3 : Wait on response channel for response
3412 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003413 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003414 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3415 errChan := make(chan error)
3416 var groupID uint32
3417 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3418 ctx: ctx,
3419 flowOrGroupAction: action,
3420 flow: flow,
3421 group: group,
3422 errChan: &errChan,
3423 }
3424 if flow != nil {
3425 groupID = flow_utils.GetGroup(flow)
3426 } else if group != nil {
3427 groupID = group.Desc.GroupId
3428 } else {
3429 return errors.New("flow-and-group-both-nil")
3430 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003431 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3432 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3433 // Derive the appropriate go routine to handle the request by a simple module operation.
3434 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3435 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3436 // Wait for handler to return error value
3437 err := <-errChan
3438 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3439 return err
3440 }
3441 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3442 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003443}
3444
3445// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003446func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003447 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003448 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003449 // block on the channel to receive an incoming mcast flow/group
3450 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003451 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3452 if mcastFlowOrGroupCb.flow != nil {
3453 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3454 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3455 log.Fields{"device-id": dh.device.Id,
3456 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003457 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3458 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3459 for _, flMgr := range dh.flowMgr {
3460 if flMgr != nil {
3461 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3462 break
3463 }
3464 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003465 // Pass the return value over the return channel
3466 *mcastFlowOrGroupCb.errChan <- err
3467 } else { // flow remove
3468 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3469 log.Fields{"device-id": dh.device.Id,
3470 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003471 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3472 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3473 for _, flMgr := range dh.flowMgr {
3474 if flMgr != nil {
3475 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3476 break
3477 }
3478 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003479 // Pass the return value over the return channel
3480 *mcastFlowOrGroupCb.errChan <- err
3481 }
3482 } else { // mcast group
3483 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3484 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3485 log.Fields{"device-id": dh.device.Id,
3486 "groupToAdd": mcastFlowOrGroupCb.group})
3487 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3488 // Pass the return value over the return channel
3489 *mcastFlowOrGroupCb.errChan <- err
3490 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3491 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3492 log.Fields{"device-id": dh.device.Id,
3493 "groupToModify": mcastFlowOrGroupCb.group})
3494 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3495 // Pass the return value over the return channel
3496 *mcastFlowOrGroupCb.errChan <- err
3497 } else { // group remove
3498 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3499 log.Fields{"device-id": dh.device.Id,
3500 "groupToRemove": mcastFlowOrGroupCb.group})
3501 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3502 // Pass the return value over the return channel
3503 *mcastFlowOrGroupCb.errChan <- err
3504 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003505 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003506 case <-stopHandler:
3507 dh.mcastHandlerRoutineActive[routineIndex] = false
3508 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003509 }
3510 }
3511}
kesavand62126212021-01-12 04:56:06 -05003512
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003513// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003514func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003515 for i, v := range dh.stopMcastHandlerRoutine {
3516 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003517 select {
3518 case v <- true:
3519 case <-time.After(time.Second * 5):
3520 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3521 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003522 }
3523 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003524
3525 if dh.incomingMcastFlowOrGroup != nil {
3526 for k := range dh.incomingMcastFlowOrGroup {
3527 if dh.incomingMcastFlowOrGroup[k] != nil {
3528 dh.incomingMcastFlowOrGroup[k] = nil
3529 }
3530 }
3531 dh.incomingMcastFlowOrGroup = nil
3532 }
3533
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003534 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003535 logger.Debug(ctx, "stopped all mcast handler routines")
3536}
3537
Akash Kankanala041a2122024-10-16 15:49:22 +05303538// nolint: unparam
kesavand62126212021-01-12 04:56:06 -05003539func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003540 singleValResp := extension.SingleGetValueResponse{
3541 Response: &extension.GetValueResponse{
3542 Response: &extension.GetValueResponse_PortCoutners{
3543 PortCoutners: &extension.GetOltPortCountersResponse{},
3544 },
3545 },
3546 }
3547
Akash Kankanala041a2122024-10-16 15:49:22 +05303548 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
kesavand62126212021-01-12 04:56:06 -05003549 return &extension.SingleGetValueResponse{
3550 Response: &extension.GetValueResponse{
3551 Status: status,
3552 ErrReason: reason,
3553 },
3554 }
3555 }
3556
3557 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3558 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
Akash Kankanala041a2122024-10-16 15:49:22 +05303559 // send error response
kesavand62126212021-01-12 04:56:06 -05003560 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3561 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3562 }
3563 statIndChn := make(chan bool, 1)
3564 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3565 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
Akash Kankanala041a2122024-10-16 15:49:22 +05303566 // request openOlt agent to send the the port statistics indication
kesavand62126212021-01-12 04:56:06 -05003567
3568 go func() {
3569 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3570 if err != nil {
3571 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3572 }
3573 }()
3574 select {
3575 case <-statIndChn:
Akash Kankanala041a2122024-10-16 15:49:22 +05303576 // indication received for ports stats
kesavand62126212021-01-12 04:56:06 -05003577 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3578 case <-time.After(oltPortInfoTimeout * time.Second):
3579 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3580 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3581 case <-ctx.Done():
3582 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3583 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3584 }
3585 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
Akash Kankanala041a2122024-10-16 15:49:22 +05303586 // get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003587 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003588 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3589 cmnni := dh.portStats.collectNNIMetrics(intfID)
3590 if cmnni == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303591 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003592 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3593 }
3594 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3595 return &singleValResp
kesavand62126212021-01-12 04:56:06 -05003596 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3597 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003598 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003599 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3600 cmpon := dh.portStats.collectPONMetrics(intfID)
3601 if cmpon == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05303602 // TODO define the error reason
kesavand62126212021-01-12 04:56:06 -05003603 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3604 }
3605 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3606 return &singleValResp
3607 }
3608 }
3609 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3610}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303611
Akash Kankanala041a2122024-10-16 15:49:22 +05303612//nolint:unparam
Akash Soni3bcf5e02024-12-03 08:01:48 +05303613func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303614 singleValResp := extension.SingleGetValueResponse{
3615 Response: &extension.GetValueResponse{
3616 Status: extension.GetValueResponse_OK,
3617 Response: &extension.GetValueResponse_OffloadedAppsStats{
3618 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3619 },
3620 },
3621 }
3622
3623 return &singleValResp
3624}
3625
Akash Kankanala041a2122024-10-16 15:49:22 +05303626//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303627func (dh *DeviceHandler) setOltOffload(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
Akash Soni3c75ad72024-12-23 12:09:48 +05303628 singleValResp := extension.SingleSetValueResponse{
3629 Response: &extension.SetValueResponse{
3630 Status: extension.SetValueResponse_OK,
3631 },
3632 }
3633
3634 return &singleValResp
3635}
3636
Akash Kankanala041a2122024-10-16 15:49:22 +05303637//nolint:unparam
Akash Soni3c75ad72024-12-23 12:09:48 +05303638func (dh *DeviceHandler) setOnuOffload(ctx context.Context, config *extension.AppOffloadOnuConfig) *extension.SingleSetValueResponse {
Akash Soni3bcf5e02024-12-03 08:01:48 +05303639 singleValResp := extension.SingleSetValueResponse{
3640 Response: &extension.SetValueResponse{
3641 Status: extension.SetValueResponse_OK,
3642 },
3643 }
3644
3645 return &singleValResp
3646}
3647
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303648func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303649 singleValResp := extension.SingleGetValueResponse{
3650 Response: &extension.GetValueResponse{
3651 Response: &extension.GetValueResponse_OnuPonCounters{
3652 OnuPonCounters: &extension.GetOnuCountersResponse{},
3653 },
3654 },
3655 }
3656
Akash Kankanala041a2122024-10-16 15:49:22 +05303657 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303658 return &extension.SingleGetValueResponse{
3659 Response: &extension.GetValueResponse{
3660 Status: status,
3661 ErrReason: reason,
3662 },
3663 }
3664 }
3665 intfID := onuPonInfo.IntfId
3666 onuID := onuPonInfo.OnuId
3667 onuKey := dh.formOnuKey(intfID, onuID)
3668
3669 if _, ok := dh.onus.Load(onuKey); !ok {
3670 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3671 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3672 }
3673 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3674 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3675 if cmnni == nil {
3676 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3677 }
3678 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3679 return &singleValResp
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303680}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003681
nikesh.krishnanc8473432023-06-14 12:14:54 +05303682func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05303683 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3684 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3685 if err != nil {
3686 return nil, err
3687 }
3688 return OnuInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05303689}
3690
3691func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
nikesh.krishnanc8473432023-06-14 12:14:54 +05303692 Intf := oop.Interface{IntfId: intfID}
3693 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3694 if err != nil {
3695 return nil, err
3696 }
3697 return IntfInfo, nil
nikesh.krishnanc8473432023-06-14 12:14:54 +05303698}
3699
Gamze Abaka85e9a142021-05-26 13:41:39 +00003700func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00003701 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3702 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3703 if err != nil {
3704 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3705 return generateSingleGetValueErrorResponse(err)
3706 }
3707 return &extension.SingleGetValueResponse{
3708 Response: &extension.GetValueResponse{
3709 Status: extension.GetValueResponse_OK,
3710 Response: &extension.GetValueResponse_RxPower{
3711 RxPower: &extension.GetRxPowerResponse{
3712 IntfId: rxPowerRequest.IntfId,
3713 OnuId: rxPowerRequest.OnuId,
3714 Status: rxPower.Status,
3715 FailReason: rxPower.FailReason.String(),
3716 RxPower: rxPower.RxPowerMeanDbm,
3717 },
3718 },
3719 },
3720 }
3721}
3722
praneeth nalmas55616d62023-02-06 09:19:18 +05303723func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05303724 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
praneeth nalmas55616d62023-02-06 09:19:18 +05303725 return &extension.SingleGetValueResponse{
3726 Response: &extension.GetValueResponse{
3727 Status: status,
3728 ErrReason: reason,
3729 },
3730 }
3731 }
3732
3733 resp := extension.SingleGetValueResponse{
3734 Response: &extension.GetValueResponse{
3735 Status: extension.GetValueResponse_OK,
3736 Response: &extension.GetValueResponse_OltRxPower{
3737 OltRxPower: &extension.GetOltRxPowerResponse{},
3738 },
3739 },
3740 }
3741
3742 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3743 portLabel := OltRxPowerRequest.PortLabel
3744 serialNumber := OltRxPowerRequest.OnuSn
3745
3746 portInfo := strings.Split(portLabel, "-")
3747 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3748
3749 if err != nil {
3750 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3751 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3752 }
3753
3754 if portInfo[0] != "pon" {
3755 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3756 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3757 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303758
3759 if serialNumber != "" {
praneeth nalmas55616d62023-02-06 09:19:18 +05303760 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3761 if onuDev != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05303762 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3763 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3764 if err != nil {
praneeth nalmas55616d62023-02-06 09:19:18 +05303765 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3766 return generateSingleGetValueErrorResponse(err)
praneeth nalmas55616d62023-02-06 09:19:18 +05303767 }
3768
3769 rxPowerValue := extension.RxPower{}
3770 rxPowerValue.OnuSn = onuDev.serialNumber
3771 rxPowerValue.Status = rxPower.GetStatus()
3772 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3773 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3774
3775 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
praneeth nalmas55616d62023-02-06 09:19:18 +05303776 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303777 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3778 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3779 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303780 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303781 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303782 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303783 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05303784 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3785 if err != nil {
3786 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3787 } else {
praneeth nalmas55616d62023-02-06 09:19:18 +05303788 rxPowerValue := extension.RxPower{}
3789 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3790 rxPowerValue.Status = rxPower.GetStatus()
3791 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3792 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3793
3794 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3795 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303796 }
3797 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3798 return true
3799 })
3800 }
3801 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3802 return &resp
3803}
3804
Akash Kankanala041a2122024-10-16 15:49:22 +05303805// nolint: unparam
Gamze Abaka85e9a142021-05-26 13:41:39 +00003806func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
Akash Kankanala041a2122024-10-16 15:49:22 +05303807 errResp := func(status extension.GetValueResponse_Status, reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
Gamze Abaka85e9a142021-05-26 13:41:39 +00003808 return &extension.SingleGetValueResponse{
3809 Response: &extension.GetValueResponse{
3810 Status: status,
3811 ErrReason: reason,
3812 },
3813 }
3814 }
3815
3816 if err != nil {
3817 if e, ok := status.FromError(err); ok {
3818 switch e.Code() {
3819 case codes.Internal:
3820 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3821 case codes.DeadlineExceeded:
3822 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3823 case codes.Unimplemented:
3824 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3825 case codes.NotFound:
3826 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3827 }
3828 }
3829 }
3830
3831 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3832}
khenaidoo106c61a2021-08-11 18:05:46 -04003833
3834/*
3835Helper functions to communicate with Core
3836*/
3837
3838func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3839 cClient, err := dh.coreClient.GetCoreServiceClient()
3840 if err != nil || cClient == nil {
3841 return nil, err
3842 }
3843 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3844 defer cancel()
3845 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3846}
3847
khenaidoodc2116e2021-10-19 17:33:19 -04003848func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003849 cClient, err := dh.coreClient.GetCoreServiceClient()
3850 if err != nil || cClient == nil {
3851 return nil, err
3852 }
3853 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3854 defer cancel()
3855 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3856}
3857
khenaidoodc2116e2021-10-19 17:33:19 -04003858func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003859 cClient, err := dh.coreClient.GetCoreServiceClient()
3860 if err != nil || cClient == nil {
3861 return err
3862 }
3863 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3864 defer cancel()
3865 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3866 return err
3867}
3868
3869func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3870 cClient, err := dh.coreClient.GetCoreServiceClient()
3871 if err != nil || cClient == nil {
3872 return nil, err
3873 }
3874 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3875 defer cancel()
3876 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3877}
3878
3879func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3880 cClient, err := dh.coreClient.GetCoreServiceClient()
3881 if err != nil || cClient == nil {
3882 return nil, err
3883 }
3884 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3885 defer cancel()
3886 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3887}
3888
3889func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3890 cClient, err := dh.coreClient.GetCoreServiceClient()
3891 if err != nil || cClient == nil {
3892 return err
3893 }
3894 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3895 defer cancel()
3896 _, err = cClient.DeviceUpdate(subCtx, device)
3897 return err
3898}
3899
khenaidoodc2116e2021-10-19 17:33:19 -04003900func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003901 cClient, err := dh.coreClient.GetCoreServiceClient()
3902 if err != nil || cClient == nil {
3903 return nil, err
3904 }
3905 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3906 defer cancel()
3907 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3908}
3909
khenaidoodc2116e2021-10-19 17:33:19 -04003910func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003911 cClient, err := dh.coreClient.GetCoreServiceClient()
3912 if err != nil || cClient == nil {
3913 return err
3914 }
3915 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3916 defer cancel()
3917 _, err = cClient.SendPacketIn(subCtx, pkt)
3918 return err
3919}
3920
3921func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3922 cClient, err := dh.coreClient.GetCoreServiceClient()
3923 if err != nil || cClient == nil {
3924 return err
3925 }
3926 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3927 defer cancel()
3928 _, err = cClient.PortCreated(subCtx, port)
3929 return err
3930}
3931
khenaidoodc2116e2021-10-19 17:33:19 -04003932func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003933 cClient, err := dh.coreClient.GetCoreServiceClient()
3934 if err != nil || cClient == nil {
3935 return err
3936 }
3937 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3938 defer cancel()
3939 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3940 return err
3941}
3942
khenaidoodc2116e2021-10-19 17:33:19 -04003943func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003944 cClient, err := dh.coreClient.GetCoreServiceClient()
3945 if err != nil || cClient == nil {
3946 return err
3947 }
3948 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3949 defer cancel()
3950 _, err = cClient.PortStateUpdate(subCtx, portState)
3951 return err
3952}
3953
khenaidoodc2116e2021-10-19 17:33:19 -04003954func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003955 cClient, err := dh.coreClient.GetCoreServiceClient()
3956 if err != nil || cClient == nil {
3957 return nil, err
3958 }
3959 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3960 defer cancel()
3961 return cClient.GetDevicePort(subCtx, portFilter)
3962}
3963
nikesh.krishnanc8473432023-06-14 12:14:54 +05303964func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
3965 cClient, err := dh.coreClient.GetCoreServiceClient()
3966 if err != nil || cClient == nil {
3967 return nil, err
3968 }
3969 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3970 defer cancel()
3971 return cClient.GetPorts(subCtx, portFilter)
3972}
3973
khenaidoo106c61a2021-08-11 18:05:46 -04003974/*
3975Helper functions to communicate with child adapter
3976*/
3977
khenaidoodc2116e2021-10-19 17:33:19 -04003978func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003979 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3980 if err != nil || aClient == nil {
3981 return err
3982 }
3983 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3984 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3985 defer cancel()
3986 _, err = aClient.OmciIndication(subCtx, response)
3987 return err
3988}
3989
khenaidoodc2116e2021-10-19 17:33:19 -04003990func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003991 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3992 if err != nil || aClient == nil {
3993 return err
3994 }
3995 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3996 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3997 defer cancel()
3998 _, err = aClient.OnuIndication(subCtx, onuInd)
3999 return err
4000}
4001
khenaidoodc2116e2021-10-19 17:33:19 -04004002func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004003 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4004 if err != nil || aClient == nil {
4005 return err
4006 }
4007 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4008 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4009 defer cancel()
4010 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4011 return err
4012}
4013
khenaidoodc2116e2021-10-19 17:33:19 -04004014func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004015 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4016 if err != nil || aClient == nil {
4017 return err
4018 }
4019 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4020 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4021 defer cancel()
4022 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4023 return err
4024}
4025
khenaidoodc2116e2021-10-19 17:33:19 -04004026func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004027 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4028 if err != nil || aClient == nil {
4029 return err
4030 }
4031 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4032 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4033 defer cancel()
4034 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4035 return err
4036}
4037
4038/*
4039Helper functions for remote communication
4040*/
4041
4042// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4043// supports is deleted
4044func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4045 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4046
4047 dh.lockChildAdapterClients.Lock()
4048 defer dh.lockChildAdapterClients.Unlock()
4049 if _, ok := dh.childAdapterClients[endpoint]; ok {
4050 // Already set
4051 return nil
4052 }
4053
4054 // Setup child's adapter grpc connection
4055 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004056 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4057 dh.cfg.AdapterEndpoint,
4058 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004059 "onu_inter_adapter_service.OnuInterAdapterService",
4060 dh.onuInterAdapterRestarted,
4061 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004062 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4063 return err
4064 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304065 retryCodes := []codes.Code{
4066 codes.Unavailable, // server is currently unavailable
4067 codes.DeadlineExceeded, // deadline for the operation was exceeded
4068 }
4069 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4070 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 -04004071
nikesh.krishnand9812542023-08-01 18:31:39 +05304072 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004073 // Wait until we have a connection to the child adapter.
4074 // Unlimited retries or until context expires
4075 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4076 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4077 for {
4078 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4079 if err == nil && client != nil {
4080 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4081 break
4082 }
4083 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4084 // Backoff
4085 if err = backoff.Backoff(subCtx); err != nil {
4086 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4087 break
4088 }
4089 }
4090 return nil
4091}
4092
khenaidoodc2116e2021-10-19 17:33:19 -04004093func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004094 // First check from cache
4095 dh.lockChildAdapterClients.RLock()
4096 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4097 dh.lockChildAdapterClients.RUnlock()
4098 return cgClient.GetOnuInterAdapterServiceClient()
4099 }
4100 dh.lockChildAdapterClients.RUnlock()
4101
4102 // Set the child connection - can occur on restarts
4103 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4104 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4105 cancel()
4106 if err != nil {
4107 return nil, err
4108 }
4109
4110 // Get the child client now
4111 dh.lockChildAdapterClients.RLock()
4112 defer dh.lockChildAdapterClients.RUnlock()
4113 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4114 return cgClient.GetOnuInterAdapterServiceClient()
4115 }
4116 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4117}
4118
4119func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4120 dh.lockChildAdapterClients.Lock()
4121 defer dh.lockChildAdapterClients.Unlock()
4122 for key, client := range dh.childAdapterClients {
4123 client.Stop(ctx)
4124 delete(dh.childAdapterClients, key)
4125 }
4126}
4127
khenaidooefff76e2021-12-15 16:51:30 -05004128// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4129func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4130 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004131 return nil
4132}
4133
khenaidooefff76e2021-12-15 16:51:30 -05004134// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4135func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4136 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004137 return nil
4138 }
khenaidooefff76e2021-12-15 16:51:30 -05004139 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004140}
Girish Gowdra950326e2021-11-05 12:43:24 -07004141
4142func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4143 dh.lockDevice.Lock()
4144 defer dh.lockDevice.Unlock()
4145 dh.isDeviceDeletionInProgress = flag
4146}
4147
4148func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4149 dh.lockDevice.RLock()
4150 defer dh.lockDevice.RUnlock()
4151 return dh.isDeviceDeletionInProgress
4152}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004153
4154// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4155// Returns false if waiting timed out.
4156func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4157 c := make(chan struct{})
4158 go func() {
4159 defer close(c)
4160 wg.Wait()
4161 }()
4162 select {
4163 case <-c:
4164 return true // completed normally
4165 case <-time.After(timeout):
4166 return false // timed out
4167 }
4168}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304169
4170func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4171 val, err := json.Marshal(signature)
4172 if err != nil {
4173 logger.Error(ctx, "failed-to-marshal")
4174 return
4175 }
4176 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4177 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4178 }
4179}
4180
4181func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4182 var signature uint32
4183
4184 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4185 if er == nil {
4186 if Value != nil {
4187 Val, er := kvstore.ToByte(Value.Value)
4188 if er != nil {
4189 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4190 return signature
4191 }
4192 if er = json.Unmarshal(Val, &signature); er != nil {
4193 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4194 return signature
4195 }
4196 }
4197 }
4198 return signature
4199}