blob: 48eff8da698037a94c3968cd50380c27d6aad3c0 [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 {
khenaidoo106c61a2021-08-11 18:05:46 -040082 cm *config.ConfigManager
83 device *voltha.Device
84 cfg *conf.AdapterFlags
85 coreClient *vgrpc.Client
86 childAdapterClients map[string]*vgrpc.Client
87 lockChildAdapterClients sync.RWMutex
88 EventProxy eventif.EventProxy
89 openOLT *OpenOLT
khenaidooefff76e2021-12-15 16:51:30 -050090 exitChannel chan struct{}
khenaidoo106c61a2021-08-11 18:05:46 -040091 lockDevice sync.RWMutex
92 Client oop.OpenoltClient
93 transitionMap *TransitionMap
94 clientCon *grpc.ClientConn
95 flowMgr []*OpenOltFlowMgr
96 groupMgr *OpenOltGroupMgr
97 eventMgr *OpenOltEventMgr
98 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053099 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700100
101 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530102
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700103 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
104 // if the value is true that means the OnuDiscovery indication
105 // is currently being processed and thus we can ignore concurrent requests
106 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
107 // if we do it means something went wrong and we need to retry
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700108 discOnus sync.Map
109 onus sync.Map
110 portStats *OpenOltStatisticsMgr
111 metrics *pmmetrics.PmMetrics
112 stopCollector chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000113 isCollectorActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700114 stopHeartbeatCheck chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000115 isHeartbeatCheckActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700116 activePorts sync.Map
117 stopIndications chan bool
118 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700119
Mahir Gunyelb0046752021-02-26 13:51:05 -0800120 totalPonPorts uint32
121 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
122 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800123
124 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
125 // 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 -0700126 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
127 stopMcastHandlerRoutine []chan bool
128 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000129
130 adapterPreviouslyConnected bool
131 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700132
133 isDeviceDeletionInProgress bool
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530134 heartbeatSignature uint32
Nandita Biradar1b590f12024-09-27 10:56:28 +0530135 prevOperStatus common.OperStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700136}
137
Mahir Gunyela2e68702022-12-07 00:00:42 -0800138// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700139type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400140 deviceID string
141 deviceType string
142 serialNumber string
143 onuID uint32
144 intfID uint32
145 proxyDeviceID string
146 losRaised bool
147 rdiRaised bool
148 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700149}
150
Mahir Gunyelb0046752021-02-26 13:51:05 -0800151type onuIndicationMsg struct {
152 ctx context.Context
153 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800154}
155
156type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800157 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800158 stopChannel chan struct{}
159}
160
Mahir Gunyela2e68702022-12-07 00:00:42 -0800161// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
162// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
163// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
164// 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 -0800165type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400166 ctx context.Context // Flow/group handler context
167 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
168 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
169 group *of.OfpGroupEntry // Group message (can be nil or valid group)
170 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800171}
172
Naga Manjunath7615e552019-10-11 22:35:47 +0530173var pmNames = []string{
174 "rx_bytes",
175 "rx_packets",
176 "rx_mcast_packets",
177 "rx_bcast_packets",
178 "tx_bytes",
179 "tx_packets",
180 "tx_mcast_packets",
181 "tx_bcast_packets",
182}
183
Mahir Gunyela2e68702022-12-07 00:00:42 -0800184// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400185func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700186 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700187 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700188 device.deviceType = deviceTp
189 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700190 device.onuID = onuID
191 device.intfID = intfID
192 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530193 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400194 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700195 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530196}
197
Mahir Gunyela2e68702022-12-07 00:00:42 -0800198// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400199func 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 -0700200 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530201 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800202 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400203 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400204 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700205 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700206 dh.device = cloned
207 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500208 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700209 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000210 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
211 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530212 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 -0500213 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800214 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800215 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400216 dh.childAdapterClients = make(map[string]*vgrpc.Client)
217 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300218 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530219 if dh.kvStore == nil {
220 logger.Error(ctx, "Failed to setup KV store")
221 return nil
222 }
223
Girish Gowdra491a9c62021-01-06 16:43:07 -0800224 // Create a slice of buffered channels for handling concurrent mcast flow/group.
225 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700226 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
227 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800228 for i := range dh.incomingMcastFlowOrGroup {
229 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800230 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800231 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
232 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
233 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
234 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700235 dh.mcastHandlerRoutineActive[i] = true
236 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800237 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700238 //TODO initialize the support classes.
239 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530240}
241
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530242func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
243 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
244 switch storeType {
245 case "etcd":
246 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
Abhay Kumar9bcfeb22024-07-12 09:14:25 +0530247 case "redis":
248 return kvstore.NewRedisClient(address, timeout, false)
249 case "redis-sentinel":
250 return kvstore.NewRedisClient(address, timeout, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530251 }
252 return nil, errors.New("unsupported-kv-store")
253}
254
255// SetKVClient sets the KV client and return a kv backend
256func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
257 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
258 if err != nil {
259 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
260 return nil
261 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530262 kvbackend := &db.Backend{
263 Client: kvClient,
264 StoreType: backend,
265 Address: addr,
266 Timeout: rsrcMgr.KvstoreTimeout,
267 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
268
269 return kvbackend
270}
271
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000272// CloseKVClient closes open KV clients
273func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
274 if dh.resourceMgr != nil {
275 for _, rscMgr := range dh.resourceMgr {
276 if rscMgr != nil {
277 rscMgr.CloseKVClient(ctx)
278 }
279 }
280 }
281 if dh.flowMgr != nil {
282 for _, flMgr := range dh.flowMgr {
283 if flMgr != nil {
284 flMgr.CloseKVClient(ctx)
285 }
286 }
287 }
288}
289
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530290// start save the device to the data model
291func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700292 dh.lockDevice.Lock()
293 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000294 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700295 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000296 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530297}
298
khenaidooefff76e2021-12-15 16:51:30 -0500299// Stop stops the device handler
300func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700301 dh.lockDevice.Lock()
302 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000303 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500304 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400305
khenaidooefff76e2021-12-15 16:51:30 -0500306 // Delete (which will stop also) all grpc connections to the child adapters
307 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000308 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530309}
310
ssiddiqui04386ee2021-08-23 21:58:25 +0530311func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
312 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
313 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
314 if pooledIntfID == intfID {
315 return resourceRanges.GetTechnology()
316 }
317 }
318 }
319 return ""
320}
321
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400322func macifyIP(ip net.IP) string {
323 if len(ip) > 0 {
324 oct1 := strconv.FormatInt(int64(ip[12]), 16)
325 oct2 := strconv.FormatInt(int64(ip[13]), 16)
326 oct3 := strconv.FormatInt(int64(ip[14]), 16)
327 oct4 := strconv.FormatInt(int64(ip[15]), 16)
328 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
329 }
330 return ""
331}
332
Neha Sharma96b7bf22020-06-15 10:37:32 +0000333func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400334 var genmac string
335 var addr net.IP
336 var ips []string
337 var err error
338
Neha Sharma96b7bf22020-06-15 10:37:32 +0000339 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400340
341 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000342 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400343
344 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000345 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400346 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000347 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400348 }
349 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000350 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530351 log.Fields{"host": ips[0],
352 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400353 return genmac, nil
354 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000355 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400356 }
357
358 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000359 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530360 log.Fields{"host": host,
361 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400362 return genmac, nil
363}
364
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530365func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700366 slist := strings.Split(mac, ":")
367 result := make([]uint32, len(slist))
368 var err error
369 var tmp int64
370 for index, val := range slist {
371 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
372 return []uint32{1, 2, 3, 4, 5, 6}
373 }
374 result[index] = uint32(tmp)
375 }
376 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530377}
378
Mahir Gunyela2e68702022-12-07 00:00:42 -0800379// 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 -0800380func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530381
David K. Bainbridge794735f2020-02-11 21:01:37 -0800382 switch portType {
383 case voltha.Port_ETHERNET_NNI:
384 return fmt.Sprintf("nni-%d", portNum), nil
385 case voltha.Port_PON_OLT:
386 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700387 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800388
Girish Kumarf26e4882020-03-05 06:49:10 +0000389 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530390}
391
Elia Battiston596406d2022-02-02 12:19:00 +0100392func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
393 if speedMbps == 0 {
394 //In case it was not set in the indication
395 //and no other value was provided
396 speedMbps = defaultPortSpeedMbps
397 }
398
399 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
400 switch speedMbps {
401 case 1000000:
402 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
403 case 100000:
404 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
405 case 40000:
406 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
407 case 10000:
408 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
409 case 1000:
410 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
411 case 100:
412 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
413 case 10:
414 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
415 }
416
417 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
418
419 port := &of.OfpPort{
420 HwAddr: macAddressToUint32Array(macAddress),
421 Config: 0,
422 State: uint32(of.OfpPortState_OFPPS_LIVE),
423 Curr: capacity,
424 Advertised: capacity,
425 Peer: capacity,
426 CurrSpeed: speedMbps * 1000, //kbps
427 MaxSpeed: speedMbps * 1000, //kbps
428 }
429
430 return port
431}
432
433func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000434 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700435 if state == "up" {
436 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500437 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500438 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700439 } else {
440 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500441 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700442 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700443 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400444 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800445 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000446 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400447 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500448
khenaidoo106c61a2021-08-11 18:05:46 -0400449 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400450 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400451 DeviceId: dh.device.Id,
452 Port: portNum,
453 })
454 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000455 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400456 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400457 DeviceId: dh.device.Id,
458 PortType: portType,
459 PortNo: portNum,
460 OperStatus: operStatus})
461 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400462 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
463 "device-id": dh.device.Id,
464 "port-type": portType,
465 "port-number": portNum,
466 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500467 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400468 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500469 }
khenaidoo106c61a2021-08-11 18:05:46 -0400470
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400471 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400472 port = &voltha.Port{
473 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700474 PortNo: portNum,
475 Label: label,
476 Type: portType,
477 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100478 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700479 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000480 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700481 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400482 err = dh.createPortInCore(ctx, port)
483 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000484 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800485 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000486 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400487 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000488 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530489 return nil
490}
491
Kent Hagermane6ff1012020-07-14 15:07:53 -0400492func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400493 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530494 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400495 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
496 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530497 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800498 dh.lockDevice.Lock()
499 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530500 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530501}
502
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700503// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530504// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800505func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000506 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700507 defer func() {
508 dh.lockDevice.Lock()
509 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530510 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700511 dh.lockDevice.Unlock()
512 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700513 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700514 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700515 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700516 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400517
David Bainbridgef5879ca2019-12-13 21:17:54 +0000518 // Create an exponential backoff around re-enabling indications. The
519 // maximum elapsed time for the back off is set to 0 so that we will
520 // continue to retry. The max interval defaults to 1m, but is set
521 // here for code clarity
522 indicationBackoff := backoff.NewExponentialBackOff()
523 indicationBackoff.MaxElapsedTime = 0
524 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700525
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700526 dh.lockDevice.Lock()
527 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530528 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700529 dh.lockDevice.Unlock()
530
Girish Gowdra3f974912020-03-23 20:35:18 -0700531Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700532 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400533 select {
534 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000535 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700536 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400537 default:
538 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100539
540 select {
541 case <-indications.Context().Done():
542 if err != nil {
543 logger.Warnw(ctx, "error-during-enable-indications",
544 log.Fields{"err": err,
545 "device-id": dh.device.Id})
546 }
547
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400548 // Use an exponential back off to prevent getting into a tight loop
549 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100550 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
551 "device-id": dh.device.Id,
552 "duration": duration,
553 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400554 if duration == backoff.Stop {
555 // If we reach a maximum then warn and reset the backoff
556 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100557 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530558 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530559 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400560 indicationBackoff.Reset()
561 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700562
563 // On failure process a backoff timer while watching for stopIndications
564 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700565 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700566 select {
567 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000568 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700569 if !backoffTimer.Stop() {
570 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700571 }
572 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700573 case <-backoffTimer.C:
574 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700575 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700576 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
577 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400578 }
579 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100580 default:
581 if err != nil {
582 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530583 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530584 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100585 // Close the stream, and re-initialize it
586 if err = indications.CloseSend(); err != nil {
587 // Ok to ignore here, because we landed here due to a problem on the stream
588 // In all probability, the closeSend call may fail
589 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
590 log.Fields{"err": err,
591 "device-id": dh.device.Id})
592 }
593 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
594 return err
595 }
596 // once we re-initialized the indication stream, continue to read indications
597 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700598 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100599 // Reset backoff if we have a successful receive
600 indicationBackoff.Reset()
601 // When OLT is admin down, ignore all indications.
602 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
603 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
604 log.Fields{"indication": indication,
605 "device-id": dh.device.Id})
606 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700607 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100608 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530609 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700610 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700611 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700612 // Close the send stream
613 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700614
Girish Gowdra3f974912020-03-23 20:35:18 -0700615 return nil
616}
617
618func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700619 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700620 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
621 if err != nil {
622 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
623 }
624 if indications == nil {
625 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
626 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700627 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700628 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400629}
630
631// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
632func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
633 switch indication.Data.(type) {
634 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
635 return true
636
637 default:
638 return false
639 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640}
641
David K. Bainbridge794735f2020-02-11 21:01:37 -0800642func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700643 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000644 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530645 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700646 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530647 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700648 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000649 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000650 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530651 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000652 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800653 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000654 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800655 }
656 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657}
658
David K. Bainbridge794735f2020-02-11 21:01:37 -0800659// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530660func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700661 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662 switch indication.Data.(type) {
663 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000664 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
665 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700666 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 -0800667 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400668 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800669 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000671 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
672 defer span.Finish()
673
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700674 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800675 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100676 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400677 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800678 }
679 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000680 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700681 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000682 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
683 defer span.Finish()
684
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700685 intfOperInd := indication.GetIntfOperInd()
686 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800687 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100688 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400689 _ = 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 -0800690 }
691 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700692 } else if intfOperInd.GetType() == "pon" {
693 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
694 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800695 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100696 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400697 _ = 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 -0800698 }
699 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000700 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700701 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530703 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530704 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000706 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
707 defer span.Finish()
708
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700709 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000710 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800711 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800712 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000714 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
715 defer span.Finish()
716
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700717 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000718 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800719 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800720 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700721 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000722 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
723 defer span.Finish()
724
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700725 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000726 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 -0800727 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000728 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400729 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800730 }
731 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700732 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000733 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
734 defer span.Finish()
735
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700736 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000737 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700738 "intf-type": pktInd.IntfId,
739 "intf-id": pktInd.IntfId,
740 "gem-port-id": pktInd.GemportId,
741 "port-no": pktInd.PortNo,
742 "device-id": dh.device.Id,
743 })
744
745 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000746 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700747 "intf-type": pktInd.IntfId,
748 "intf-id": pktInd.IntfId,
749 "gem-port-id": pktInd.GemportId,
750 "port-no": pktInd.PortNo,
751 "packet": hex.EncodeToString(pktInd.Pkt),
752 "device-id": dh.device.Id,
753 })
754 }
755
David K. Bainbridge794735f2020-02-11 21:01:37 -0800756 go func() {
757 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400758 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800759 }
760 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700761 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000762 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
763 defer span.Finish()
764
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700765 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700766 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700767 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000768 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
769 defer span.Finish()
770
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700771 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000772 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700773 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000774 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
775 defer span.Finish()
776
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700777 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000778 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
779 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700780 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530781}
782
nikesh.krishnanc8473432023-06-14 12:14:54 +0530783func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
784 onuInd := &oop.OnuIndication{
785 IntfId: intfID,
786 OnuId: onuID,
787 OperState: operState,
788 AdminState: adminState,
789 }
790 indication := &oop.Indication{
791 Data: &oop.Indication_OnuInd{
792 OnuInd: onuInd,
793 },
794 }
795 return indication
796}
797
798func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
799 onuAlarmInd := &oop.OnuAlarmIndication{
800 IntfId: intfID,
801 OnuId: onuID,
802 LosStatus: losStatus,
803 }
804 alarmInd := &oop.AlarmIndication{
805 Data: &oop.AlarmIndication_OnuAlarmInd{
806 OnuAlarmInd: onuAlarmInd,
807 },
808 }
809 return alarmInd
810}
811func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
812
813 ponlosAlarmInd := &oop.LosIndication{
814 IntfId: intfID,
815 Status: losStatus,
816 }
817 alarmInd := &oop.AlarmIndication{
818 Data: &oop.AlarmIndication_LosInd{
819 LosInd: ponlosAlarmInd,
820 },
821 }
822 return alarmInd
823}
824func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
825 go func() {
826 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
827 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
828 }
829 }()
830
831 raisedTs := time.Now().Unix()
832 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
833}
834
835func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
836
837 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
838 if err != nil {
839
840 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
841
842 return err
843 }
844 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
845
846 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
847 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
848 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
849
850 onuID := onuDeviceFromCore.ProxyAddress.OnuId
851 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
852 if err != nil {
853 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
854
855 } else {
856 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
857 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
858 switch {
859 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
860 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
861 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
862
863 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
864 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") //check bal cli login notepad
865 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
866 raisedTs := time.Now().Unix()
867 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
868
869 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
870 }
871
872 }
873
874 }
875
876 return nil
877}
878
879func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
880 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
881 DeviceId: dh.device.Id,
882 PortType: voltha.Port_PON_OLT,
883 })
884 if err != nil {
885 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
886
887 return err
888
889 }
890 for _, portFromCore := range portsFromCore.Items {
891 portNum := portFromCore.GetPortNo()
892 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
893 portOperStatusFromCore := portFromCore.OperStatus
894 portAdminStateFromCore := portFromCore.AdminState
895 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
896 if err != nil {
897 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
898 } else {
899 portLosFromOlt := ponPortFromOlt.GetLos()
900 portStateFromOlt := ponPortFromOlt.GetState()
901 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
902 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
903 "portStateFromOlt": portStateFromOlt.String(),
904 "portOperStatusFromCore": portOperStatusFromCore.String(),
905 "device-id": dh.device.Id,
906 "port": portNum})
907 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
908 raisedTs := time.Now().Unix()
909 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
910
911 }
912 switch {
913 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
914 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
915 "portStateFromOlt": portStateFromOlt.String(),
916 "portOperStatusFromCore": portOperStatusFromCore.String(),
917 "device-id": dh.device.Id,
918 "port": portNum})
919 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
920 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
921 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
922 "portStateFromOlt": portStateFromOlt.String(),
923 "portOperStatusFromCore": portOperStatusFromCore.String(),
924 "device-id": dh.device.Id,
925 "port": portNum})
926 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
927 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
928 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
929 "device-id": dh.device.Id,
930 "port": portNum})
931 default:
932 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
933 "portStateFromOlt": portStateFromOlt.String(),
934 "portOperStatusFromCore": portOperStatusFromCore.String(),
935 "device-id": dh.device.Id,
936 "port": portNum})
937
938 }
939
940 }
941
942 }
943
944 return nil
945}
946
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530947// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530948func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530949 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +0530950 // Declare deviceStateFilter to be used later
951 var deviceStateFilter *ca.DeviceStateFilter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000952 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530953 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +0530954 if err != nil {
955 return fmt.Errorf("failed to get device from core: %w", err)
956 }
957 logger.Info(ctx, "Device state", log.Fields{
958 "device-id": device.Id,
959 "CurrOperStatus": device.OperStatus,
960 "CurrConnStatus": device.ConnectStatus,
961 })
962 // Perform cleanup if the device's operational status is REBOOTED
963 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
964 // Log the device's operational status if it's REBOOTED
965 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
966 "device-id": device.Id,
967 "OperStatus": device.OperStatus,
968 })
969 dh.lockDevice.RLock()
970 // Stop the read indication only if it the routine is active
971 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
972 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
973 // on next execution of the readIndication routine.
974 if dh.isHeartbeatCheckActive {
975 dh.stopHeartbeatCheck <- true
976 }
977 if dh.isReadIndicationRoutineActive {
978 dh.stopIndications <- true
979 }
980 dh.lockDevice.RUnlock()
981 if err := dh.cleanupDeviceResources(ctx); err != nil {
982 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
983 return fmt.Errorf("cleanup device resources failed: %w", err)
984 }
985 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
986 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
987 }
988 go startHeartbeatCheck(ctx, dh)
989
990 //dh.lockDevice.RUnlock()
991
992 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
993 // Log the device's operational status if it's RECONCILING
994 logger.Info(ctx, "Device is being reconciled", log.Fields{
995 "device-id": device.Id,
996 "OperStatus": device.OperStatus,
997 })
998
999 // Perform reconciliation steps
1000 err = dh.reconcileOnus(ctx)
1001 if err != nil {
1002 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
1003 }
1004 err = dh.reconcilePonPorts(ctx)
1005 if err != nil {
1006 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301007 }
1008 }
Girish Gowdra618fa572021-09-01 17:19:29 -07001009 // instantiate the mcast handler routines.
1010 for i := range dh.incomingMcastFlowOrGroup {
1011 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
1012 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
1013 if !dh.mcastHandlerRoutineActive[i] {
1014 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1015 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1016 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1017 // for incoming mcast flow/group to be processed serially.
1018 dh.mcastHandlerRoutineActive[i] = true
1019 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1020 }
1021 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301022 // Create DeviceStateFilter with the desired operational and connection statuses
1023 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001024 DeviceId: dh.device.Id,
1025 OperStatus: voltha.OperStatus_ACTIVE,
1026 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301027 }
1028 // Log DeviceStateFilter for debugging purposes
1029 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1030 "DeviceId": deviceStateFilter.DeviceId,
1031 "OperStatus": deviceStateFilter.OperStatus,
1032 "ConnStatus": deviceStateFilter.ConnStatus,
1033 })
1034 // Synchronous call to update device state - this method is run in its own go routine
1035 if err := dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001036 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001037 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001038
1039 //Clear olt communication failure event
1040 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1041 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001042 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001043 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1044
Girish Gowdru0c588b22019-04-23 23:24:56 -04001045 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301046}
1047
1048// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301049func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001050 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001051
khenaidoo106c61a2021-08-11 18:05:46 -04001052 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001053 if err != nil || device == nil {
1054 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001055 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001056 }
1057
1058 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001059
1060 //Update the device oper state and connection status
1061 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001062 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001063 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001064 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001065
khenaidoodc2116e2021-10-19 17:33:19 -04001066 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001067 DeviceId: cloned.Id,
1068 OperStatus: cloned.OperStatus,
1069 ConnStatus: cloned.ConnectStatus,
1070 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001071 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001072 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001073
1074 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001075 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001076 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001077 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001078 }
1079 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001080 // Update onu state as down in onu adapter
1081 onuInd := oop.OnuIndication{}
1082 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001083
1084 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1085 if err != nil {
1086 return err
1087 }
1088 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001089 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001090 DeviceId: onuDevice.Id,
1091 OnuIndication: &onuInd,
1092 })
1093 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001094 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001095 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001096 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001097 "onu-indicator": onuInd,
1098 "device-type": onuDevice.Type,
1099 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -07001100 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001101 } else {
1102 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 -07001103 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001104 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001105 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001106 /* Discovered ONUs entries need to be cleared , since after OLT
1107 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301108 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001109 dh.lockDevice.Unlock()
1110
Neha Sharma96b7bf22020-06-15 10:37:32 +00001111 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001112 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301113}
1114
1115// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301116func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001117 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001118
1119 // if the connection is already available, close the previous connection (olt reboot case)
1120 if dh.clientCon != nil {
1121 if err = dh.clientCon.Close(); err != nil {
1122 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1123 } else {
1124 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1125 }
1126 }
1127
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301128 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +00001129 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001130 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1131 grpc.WithInsecure(),
1132 grpc.WithBlock(),
1133 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001134 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001135 )),
1136 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001137 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001138 )))
1139
1140 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301141 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301142 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001143 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001144 }
Akash Sonif49299a2024-04-25 12:06:37 +05301145 //Setting oper and connection state to RECONCILING and conn state to reachable
1146 cgClient, err := dh.coreClient.GetCoreServiceClient()
1147 if err != nil {
1148 return err
1149 }
1150
1151 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1152 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1153 defer cancel()
1154 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1155 DeviceId: dh.device.Id,
1156 OperStatus: voltha.OperStatus_RECONCILING,
1157 ConnStatus: voltha.ConnectStatus_REACHABLE,
1158 }); err != nil {
1159 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1160 }
1161 // 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
1162 // locally cached copy of the device struct.
1163 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1164 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1165 }
1166
Girish Gowdru0c588b22019-04-23 23:24:56 -04001167 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301168}
1169
1170// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301171func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001172 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301173 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001174 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301175}
1176
1177// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301178func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301179 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001180 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001181
1182 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001183 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301184 if err != nil || device == nil {
1185 /*TODO: needs to handle error scenarios */
1186 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1187 }
1188 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001189 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001190
1191 cloned := proto.Clone(device).(*voltha.Device)
1192 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1193 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1194 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001195
khenaidoodc2116e2021-10-19 17:33:19 -04001196 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001197 DeviceId: cloned.Id,
1198 OperStatus: cloned.OperStatus,
1199 ConnStatus: cloned.ConnectStatus,
1200 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301201 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 -04001202 }
1203
Chaitrashree G S44124192019-08-07 20:21:36 -04001204 // 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 +05301205 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001206 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301207 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001208 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001209 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1210 // all the modules initialized and ready to handle incoming ONUs.
1211
Thomas Lee S985938d2020-05-04 11:40:41 +05301212 err = dh.initializeDeviceHandlerModules(ctx)
1213 if err != nil {
1214 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 -04001215 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001216
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001217 go startHeartbeatCheck(ctx, dh)
1218
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001219 return nil
1220 }
1221
khenaidoo106c61a2021-08-11 18:05:46 -04001222 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001223 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -04001224 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001225 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001226 }
khenaidoo106c61a2021-08-11 18:05:46 -04001227 dh.populateActivePorts(ctx, ports.Items)
1228 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001229 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001230 }
1231
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001232 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301233 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 -04001234 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301235
Neha Sharma96b7bf22020-06-15 10:37:32 +00001236 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001237
1238 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001239 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001240 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001241
1242 go startHeartbeatCheck(ctx, dh)
1243
cuilin20187b2a8c32019-03-26 19:52:28 -07001244 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301245}
1246
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001247func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001248 var err error
1249 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001250
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001251 if dh.flowMgr != nil {
1252 dh.StopAllFlowRoutines(ctx)
1253 }
1254
1255 dh.CloseKVClient(ctx)
1256
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001257 if err != nil {
1258 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1259 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001260 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1261 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +00001262 // +1 is for NNI
1263 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1264 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001265 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001266 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1267 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1268 // There is only one NNI manager since multiple NNI is not supported for now
1269 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001270 // Instantiate resource manager
1271 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 -07001272 return olterrors.ErrResourceManagerInstantiating
1273 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001274 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001275 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1276 // the KV store to manage mcast group data. Provide the first instance (0th index)
1277 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1278 return olterrors.ErrGroupManagerInstantiating
1279 }
yasin saplid0566272021-12-21 09:10:30 +00001280 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001281 // Instantiate flow manager
1282 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001283 //Continue to check the rest of the ports
1284 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1285 } else {
1286 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001287 }
1288 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001289 /* TODO: Instantiate Alarm , stats , BW managers */
1290 /* Instantiating Event Manager to handle Alarms and KPIs */
1291 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1292
1293 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001294 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001295
1296 return nil
1297
1298}
1299
Neha Sharma96b7bf22020-06-15 10:37:32 +00001300func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001301 var err error
1302 var deviceInfo *oop.DeviceInfo
1303
Neha Sharma8f4e4322020-08-06 10:51:53 +00001304 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001305
1306 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001307 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001308 }
1309 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001310 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001311 }
1312
Neha Sharma96b7bf22020-06-15 10:37:32 +00001313 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001314 dh.device.Root = true
1315 dh.device.Vendor = deviceInfo.Vendor
1316 dh.device.Model = deviceInfo.Model
1317 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1318 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1319 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1320
1321 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001322 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001323 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001324 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001325 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001326 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001327 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001328 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001329 dh.device.MacAddress = genmac
1330 } else {
1331 dh.device.MacAddress = deviceInfo.DeviceId
1332 }
1333
1334 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001335 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001336 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001337 }
1338
1339 return deviceInfo, nil
1340}
1341
Neha Sharma96b7bf22020-06-15 10:37:32 +00001342func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001343 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001344
1345 defer func() {
1346 dh.lockDevice.Lock()
1347 dh.isCollectorActive = false
1348 dh.lockDevice.Unlock()
1349 }()
1350
1351 dh.lockDevice.Lock()
1352 dh.isCollectorActive = true
1353 dh.lockDevice.Unlock()
1354
Naga Manjunath7615e552019-10-11 22:35:47 +05301355 for {
1356 select {
1357 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001358 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301359 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001360 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001361
khenaidoo106c61a2021-08-11 18:05:46 -04001362 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001363 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001364 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001365 continue
1366 }
khenaidoo106c61a2021-08-11 18:05:46 -04001367 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301368 // NNI Stats
1369 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001370 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301371 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001372 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001373 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001374 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301375 }
1376 // PON Stats
1377 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001378 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301379 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1380 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001381 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001382 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301383 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001384 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001385
yasin sapli9e4c5092022-02-01 13:52:33 +00001386 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001387 if len(onuGemInfoLst) > 0 {
1388 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001389 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001390 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301391 }
1392 }
1393 }
1394}
1395
Mahir Gunyela2e68702022-12-07 00:00:42 -08001396// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301397func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001398 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001399 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301400 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301401
1402 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001403 cgClient, err := dh.coreClient.GetCoreServiceClient()
1404 if err != nil {
1405 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1406 return
1407 }
1408
1409 // Now, set the initial PM configuration for that device
1410 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001411 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301412 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301413}
1414
Mahir Gunyela2e68702022-12-07 00:00:42 -08001415// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001416func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1417 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001418 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301419 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001420 HwDesc: "open_pon",
1421 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001422 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001423 },
1424 SwitchFeatures: &of.OfpSwitchFeatures{
1425 NBuffers: 256,
1426 NTables: 2,
1427 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1428 of.OfpCapabilities_OFPC_TABLE_STATS |
1429 of.OfpCapabilities_OFPC_PORT_STATS |
1430 of.OfpCapabilities_OFPC_GROUP_STATS),
1431 },
1432 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301433}
1434
khenaidoo106c61a2021-08-11 18:05:46 -04001435// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001436func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001437 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001438 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001439 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001440 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001441 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1442 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()
1443 }
khenaidoo106c61a2021-08-11 18:05:46 -04001444 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Mahir Gunyela2e68702022-12-07 00:00:42 -08001445
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001446}
1447
Neha Sharma96b7bf22020-06-15 10:37:32 +00001448func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001449 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 -07001450 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001451 var deviceID string
1452 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001453 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001454
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001455 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001456 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001457 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 -07001458 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1459 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001460
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001461 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301462
1463 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1464
Neha Sharma96b7bf22020-06-15 10:37:32 +00001465 logger.Debugw(ctx, "omci-indication-for-a-device-not-in-cache.", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001466 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001467
khenaidoodc2116e2021-10-19 17:33:19 -04001468 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001469 ParentId: dh.device.Id,
1470 OnuId: omciInd.OnuId,
1471 ParentPortNo: ponPort,
1472 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001473 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301474 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001475 "intf-id": omciInd.IntfId,
1476 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001477 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001478 deviceType = onuDevice.Type
1479 deviceID = onuDevice.Id
1480 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001481 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001482 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001483 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001484 } else {
1485 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001486 logger.Debugw(ctx, "omci-indication-for-a-device-in-cache.", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301487 deviceType = onuInCache.(*OnuDevice).deviceType
1488 deviceID = onuInCache.(*OnuDevice).deviceID
1489 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001490 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001491 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001492
khenaidoodc2116e2021-10-19 17:33:19 -04001493 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001494 ParentDeviceId: proxyDeviceID,
1495 ChildDeviceId: deviceID,
1496 Message: omciInd.Pkt,
1497 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301498 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001499 "source": dh.openOLT.config.AdapterEndpoint,
1500 "device-type": deviceType,
1501 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001502 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001503 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001504 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001505 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301506}
1507
khenaidoo106c61a2021-08-11 18:05:46 -04001508// //ProcessInterAdapterMessage sends the proxied messages to the target device
1509// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1510// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001511// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001512// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001513// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001514// return dh.handleInterAdapterOmciMsg(ctx, msg)
1515// }
1516// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1517// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001518
kesavandb9f54fd2021-11-25 20:08:04 +05301519// ProxyOmciRequests sends the proxied OMCI message to the target device
1520func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301521 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1522 return status.Error(codes.Unavailable, "OLT unreachable")
1523 }
kesavandb9f54fd2021-11-25 20:08:04 +05301524 if omciMsgs.GetProxyAddress() == nil {
1525 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1526 if err != nil {
1527 return olterrors.NewErrNotFound("onu", log.Fields{
1528 "parent-device-id": dh.device.Id,
1529 "child-device-id": omciMsgs.ChildDeviceId}, err)
1530 }
1531 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1532 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1533 return olterrors.NewErrCommunication("send-failed", log.Fields{
1534 "parent-device-id": dh.device.Id,
1535 "child-device-id": omciMsgs.ChildDeviceId}, err)
1536 }
1537 } else {
1538 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1539 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1540 return olterrors.NewErrCommunication("send-failed", log.Fields{
1541 "parent-device-id": dh.device.Id,
1542 "child-device-id": omciMsgs.ChildDeviceId}, err)
1543 }
1544 }
1545 return nil
1546}
1547
1548func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1549 var intfID uint32
1550 var onuID uint32
1551 var connectStatus common.ConnectStatus_Types
1552 if onuDevice != nil {
1553 intfID = onuDevice.ProxyAddress.GetChannelId()
1554 onuID = onuDevice.ProxyAddress.GetOnuId()
1555 connectStatus = onuDevice.ConnectStatus
1556 } else {
1557 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1558 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1559 connectStatus = omciMsgs.GetConnectStatus()
1560 }
1561 if connectStatus != voltha.ConnectStatus_REACHABLE {
1562 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1563
1564 return olterrors.NewErrCommunication("unreachable", log.Fields{
1565 "intf-id": intfID,
1566 "onu-id": onuID}, nil)
1567 }
1568
1569 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1570 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1571
1572 onuSecOmciMsgList := omciMsgs.GetMessages()
1573
1574 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1575
1576 var omciMessage *oop.OmciMsg
1577 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1578 hex.Encode(hexPkt, onuSecOmciMsg)
1579 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1580
1581 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1582 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1583 //https://jira.opencord.org/browse/VOL-4604
1584 transid := extractOmciTransactionID(onuSecOmciMsg)
1585 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1586 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1587
1588 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1589 if err != nil {
1590 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1591 "intf-id": intfID,
1592 "onu-id": onuID,
1593 "message": omciMessage}, err)
1594 }
1595 }
1596 return nil
1597}
1598
khenaidoo106c61a2021-08-11 18:05:46 -04001599// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001600func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001601 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 -07001602
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301603 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1604 return status.Error(codes.Unavailable, "OLT unreachable")
1605 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001606 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001607 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001608 if err != nil {
1609 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001610 "parent-device-id": dh.device.Id,
1611 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001612 }
khenaidoo106c61a2021-08-11 18:05:46 -04001613 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1614 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001615 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001616 "parent-device-id": dh.device.Id,
1617 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001618 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001619 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001620 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1621 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001622 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001623 "parent-device-id": dh.device.Id,
1624 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001625 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001626 }
1627 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301628}
1629
khenaidoodc2116e2021-10-19 17:33:19 -04001630func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001631 var intfID uint32
1632 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001633 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001634 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001635 intfID = onuDevice.ProxyAddress.GetChannelId()
1636 onuID = onuDevice.ProxyAddress.GetOnuId()
1637 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001638 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001639 intfID = omciMsg.GetProxyAddress().GetChannelId()
1640 onuID = omciMsg.GetProxyAddress().GetOnuId()
1641 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001642 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001643 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001644 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 -08001645
Thomas Lee S94109f12020-03-03 16:39:29 +05301646 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001647 "intf-id": intfID,
1648 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001649 }
1650
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001651 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1652 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301653 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001654 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001655 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1656 hex.Encode(hexPkt, omciMsg.Message)
1657 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1658
1659 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1660 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1661 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001662 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001663 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001664
Neha Sharma8f4e4322020-08-06 10:51:53 +00001665 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001666 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301667 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001668 "intf-id": intfID,
1669 "onu-id": onuID,
1670 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001671 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001672 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001673}
1674
David K. Bainbridge794735f2020-02-11 21:01:37 -08001675func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301676 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 +00001677 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001678 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001679 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001680 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301681 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301682 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001683 st, _ := status.FromError(err)
1684 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001685 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1686
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001687 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301688 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001689 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001690 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001691 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001692 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001693 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001694}
1695
Mahir Gunyela2e68702022-12-07 00:00:42 -08001696// getChildDevice function can be used in general to get child device, if not found in cache the function will
1697// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301698func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1699 var InCacheOnuDev *OnuDevice
1700 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1701 if onuInCache.(*OnuDevice).serialNumber == sn {
1702 InCacheOnuDev = onuInCache.(*OnuDevice)
1703 return false
1704 }
1705 return true
1706 })
1707 //Got the onu device from cache return
1708 if InCacheOnuDev != nil {
1709 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1710 return InCacheOnuDev
1711 }
1712 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1713 ParentId: dh.device.Id,
1714 SerialNumber: sn,
1715 ParentPortNo: parentPortNo,
1716 })
1717 //No device found in core return nil
1718 if onuDevice == nil {
1719 return nil
1720 }
1721 onuID := onuDevice.ProxyAddress.OnuId
1722 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1723 onuKey := dh.formOnuKey(intfID, onuID)
1724
1725 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1726 dh.onus.Store(onuKey, onuDev)
1727 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1728 return onuDev
1729}
1730
1731func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001732 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001733 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301734 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001735
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301736 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1737 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1738 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1739 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1740 if onuDev != nil {
1741 var onuGemInfo *rsrcMgr.OnuGemInfo
1742 var err error
1743 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1744 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1745 return false, err
1746 }
1747 if onuGemInfo != nil {
1748 for _, uni := range onuGemInfo.UniPorts {
1749 uniID := plt.UniIDFromPortNum(uni)
1750 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1751 if len(tpIDs) != 0 {
1752 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1753 tpInstExists = true
1754 break
1755 }
1756 }
1757 }
1758 }
1759 return tpInstExists, nil
1760 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301761
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301762 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1763 ParentId: dh.device.Id,
1764 SerialNumber: sn,
1765 ParentPortNo: parentPortNo,
1766 })
1767 if onuDevice != nil {
1768 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1769 return true, nil
1770 }
1771 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1772
1773 return false, nil
1774
1775}
1776
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001777// processDiscONULOSClear clears the LOS Alarm if it's needed
1778func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301779 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001780 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301781
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001782 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1783 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1784 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1785 OnuLosRaise event sent for it */
1786 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1787 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1788 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1789 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1790 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1791 "currentIntfId": onuDiscInd.GetIntfId()})
1792 // TODO:: Should we need to ignore raising OnuLosClear event
1793 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301794 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001795 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1796 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1797 alarmInd.LosStatus = statusCheckOff
1798 go func() {
1799 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1800 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1801 }
1802 }()
1803 // stop iterating
1804 return false
1805 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301806 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001807 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301808}
1809
1810func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301811 var error error
1812
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301813 channelID := onuDiscInd.GetIntfId()
1814 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1815
1816 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301817 defer func() {
1818 if error != nil {
1819 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1820 } else {
1821 // once the function completes set the value to false so that
1822 // we know the processing has inProcess.
1823 // Note that this is done after checking if we are already processing
1824 // to avoid changing the value from a different thread
1825 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1826 dh.discOnus.Store(sn, false)
1827 }
1828 }()
1829
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301830 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1831
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301832 tpInstExists, error := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1833 if error != nil {
1834 return error
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301835 }
1836 if tpInstExists {
1837 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001838 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001839 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001840 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001841 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1842
1843 // if the ONU existed, handle the LOS Alarm
1844 if existing {
1845
1846 if inProcess.(bool) {
1847 // if we're currently processing the ONU on a different thread, do nothing
1848 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1849 return nil
1850 }
1851 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1852 // then continue processing it
1853 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1854
1855 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001856 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301857 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001858 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001859
1860 // check the ONU is already know to the OLT
1861 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301862 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001863 ParentId: dh.device.Id,
1864 SerialNumber: sn,
1865 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001866
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301867 if error != nil {
1868 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1869 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001870 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 -08001871 switch e.Code() {
1872 case codes.Internal:
1873 // this probably means NOT FOUND, so just create a new device
1874 onuDevice = nil
1875 case codes.DeadlineExceeded:
1876 // if the call times out, cleanup and exit
1877 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301878 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1879 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001880 }
1881 }
1882 }
1883
1884 if onuDevice == nil {
1885 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001886 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001887 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001888 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301889 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001890
Neha Sharma96b7bf22020-06-15 10:37:32 +00001891 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001892
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301893 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001894 // if we can't create an ID in resource manager,
1895 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001896 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301897
1898 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001899 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301900 "serial-number": sn}, error)
1901 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001902 }
1903
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301904 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001905 ParentId: dh.device.Id,
1906 ParentPortNo: parentPortNo,
1907 ChannelId: channelID,
1908 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1909 SerialNumber: sn,
1910 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301911 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001912 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001913 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 +05301914
1915 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001916 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301917 "serial-number": sn}, error)
1918 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001919 }
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301920 if error := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); error != nil {
1921 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
1922 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
1923 "onu-id": onuID,
1924 "device-id": dh.device.Id,
1925 "serial-number": sn}, error)
1926 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04001927 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001928 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301929 log.Fields{"onuDevice": onuDevice,
1930 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001931 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301932 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001933 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001934
khenaidoo106c61a2021-08-11 18:05:46 -04001935 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1936 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301937 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04001938 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301939 if error != nil {
1940
1941 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
1942 return error
khenaidoo106c61a2021-08-11 18:05:46 -04001943 }
1944
Matteo Scandolo945e4012019-12-12 14:16:11 -08001945 // we can now use the existing ONU Id
1946 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001947 //Insert the ONU into cache to use in OnuIndication.
1948 //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 +00001949 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001950 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301951 "intfId": onuDiscInd.GetIntfId(),
1952 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001953 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001954
khenaidoo106c61a2021-08-11 18:05:46 -04001955 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301956 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001957 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301958 log.Fields{"onu": onuDev,
1959 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001960
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301961 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001962 DeviceId: onuDevice.Id,
1963 ParentDeviceId: dh.device.Id,
1964 OperStatus: common.OperStatus_DISCOVERED,
1965 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301966 }); error != nil {
1967
1968 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001969 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301970 "serial-number": sn}, error)
1971 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07001972 }
khenaidoo106c61a2021-08-11 18:05:46 -04001973
Neha Sharma96b7bf22020-06-15 10:37:32 +00001974 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301975 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
1976
1977 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001978 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301979 "serial-number": sn}, error)
1980 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08001981 }
1982 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001983}
1984
Mahir Gunyelb0046752021-02-26 13:51:05 -08001985func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001986
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001987 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001988 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001989 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001990 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001991 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301992 log.Fields{"onuId": onuInd.OnuId,
1993 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301994 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001995 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001996 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301997
David K. Bainbridge794735f2020-02-11 21:01:37 -08001998 errFields := log.Fields{"device-id": dh.device.Id}
1999
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302000 if onuInCache, ok := dh.onus.Load(onuKey); ok {
2001
Mahir Gunyele77977b2019-06-27 05:36:22 -07002002 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
2003 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002004 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002005 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002006 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07002007 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
2008 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002009 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002010 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002011 errFields["onu-id"] = onuInd.OnuId
2012 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002013 }
khenaidoodc2116e2021-10-19 17:33:19 -04002014 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002015 ParentId: dh.device.Id,
2016 SerialNumber: serialNumber,
2017 OnuId: onuInd.OnuId,
2018 ParentPortNo: ponPort,
2019 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002020 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002021
David K. Bainbridge794735f2020-02-11 21:01:37 -08002022 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002023 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002024 }
2025
David K. Bainbridge794735f2020-02-11 21:01:37 -08002026 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002027 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002028 "previousIntfId": onuDevice.ParentPortNo,
2029 "currentIntfId": ponPort})
2030 }
2031
2032 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002033 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302034 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2035 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302036 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002037 }
2038 if !foundInCache {
2039 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
2040
khenaidoo106c61a2021-08-11 18:05:46 -04002041 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 -08002042
2043 }
kesavand7cf3a052020-08-28 12:49:18 +05302044 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002045 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002046 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302047 }
2048 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002049 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002050 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002051 }
2052 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002053}
2054
Neha Sharma96b7bf22020-06-15 10:37:32 +00002055func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002056 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 -07002057 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2058 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2059 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2060 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002061 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002062 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2063 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002064 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002065 onuInd.OperState = "down"
2066 }
2067 }
2068
David K. Bainbridge794735f2020-02-11 21:01:37 -08002069 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002070 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002071 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 -04002072
khenaidoodc2116e2021-10-19 17:33:19 -04002073 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002074 DeviceId: onuDevice.Id,
2075 OnuIndication: onuInd,
2076 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002077 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302078 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002079 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002080 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002081 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002082 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002083 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002084 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002085 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002086 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002087 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002088}
2089
cuilin20187b2a8c32019-03-26 19:52:28 -07002090func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2091 if serialNum != nil {
2092 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002093 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002094 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002095}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002096func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2097 decodedStr, err := hex.DecodeString(serialNum[4:])
2098 if err != nil {
2099 return nil, err
2100 }
2101 return &oop.SerialNumber{
2102 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002103 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002104 }, nil
2105}
cuilin20187b2a8c32019-03-26 19:52:28 -07002106
2107func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002108 if len(vendorSpecific) > 3 {
2109 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2110 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2111 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2112 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2113 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2114 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2115 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2116 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2117 return tmp
2118 }
2119 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002120}
2121
Mahir Gunyela2e68702022-12-07 00:00:42 -08002122// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002123func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302124 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002125}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002126
Mahir Gunyela2e68702022-12-07 00:00:42 -08002127// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002128func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2129 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302130 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002131 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302132 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002133
khenaidoodc2116e2021-10-19 17:33:19 -04002134 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002135 ParentId: dh.device.Id,
2136 OnuId: onuID,
2137 ParentPortNo: parentPort,
2138 })
2139
Girish Gowdru0c588b22019-04-23 23:24:56 -04002140 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002141 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002142 "intf-id": parentPort,
2143 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002144 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002145 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 -08002146 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302147}
2148
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002149// SendPacketInToCore sends packet-in to core
2150// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2151// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002152func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002153 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002154 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002155 "port": logicalPort,
2156 "packet": hex.EncodeToString(packetPayload),
2157 "device-id": dh.device.Id,
2158 })
2159 }
khenaidoo106c61a2021-08-11 18:05:46 -04002160
khenaidoodc2116e2021-10-19 17:33:19 -04002161 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002162 DeviceId: dh.device.Id,
2163 Port: logicalPort,
2164 Packet: packetPayload,
2165 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302166 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002167 "source": "adapter",
2168 "destination": "core",
2169 "device-id": dh.device.Id,
2170 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002171 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002172 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002173 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002174 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002175 "packet": hex.EncodeToString(packetPayload),
2176 "device-id": dh.device.Id,
2177 })
2178 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002179 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002180}
2181
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002182// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002183func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002185
2186 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2187 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002188 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002189 }
2190
Kent Hagermane6ff1012020-07-14 15:07:53 -04002191 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002192 metrics := dh.metrics.GetSubscriberMetrics()
2193 for _, m := range pmConfigs.Metrics {
2194 metrics[m.Name].Enabled = m.Enabled
2195
2196 }
2197 }
2198}
2199
khenaidoodc2116e2021-10-19 17:33:19 -04002200func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002201 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002202 var errorsList []error
2203
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002204 if dh.getDeviceDeletionInProgressFlag() {
2205 // The device itself is going to be reset as part of deletion. So nothing to be done.
2206 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2207 return nil
2208 }
2209
Girish Gowdru0c588b22019-04-23 23:24:56 -04002210 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002211 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00002212 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002213
Neha Sharma96b7bf22020-06-15 10:37:32 +00002214 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302215 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002216 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302217 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002218 if flow_utils.HasGroup(flow) {
2219 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2220 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002221 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2222 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2223 } else {
2224 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2225 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002226 }
Girish Gowdracefae192020-03-19 18:14:10 -07002227 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002228 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
2229 //The flow we want to remove is not there, there is no need to throw an error
2230 logger.Warnw(ctx, "flow-to-remove-not-found",
2231 log.Fields{
2232 "ponIf": intfID,
2233 "flowToRemove": flow,
2234 "error": err,
2235 })
2236 } else {
2237 errorsList = append(errorsList, err)
2238 }
Girish Gowdracefae192020-03-19 18:14:10 -07002239 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002240 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302241
2242 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00002243 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002244 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302245 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002246 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302247 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002248 if flow_utils.HasGroup(flow) {
2249 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2250 } else {
yasin saplid0566272021-12-21 09:10:30 +00002251 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002252 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2253 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2254 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2255 } else {
yasin saplid0566272021-12-21 09:10:30 +00002256 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002257 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002258 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002259 if err != nil {
2260 errorsList = append(errorsList, err)
2261 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302262 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002263 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002264
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002265 return errorsList
2266}
2267
2268func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2269 var err error
2270 var errorsList []error
2271
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002272 if dh.getDeviceDeletionInProgressFlag() {
2273 // The device itself is going to be reset as part of deletion. So nothing to be done.
2274 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2275 return nil
2276 }
2277
Girish Gowdracefae192020-03-19 18:14:10 -07002278 // 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 +00002279 if groups != nil {
2280 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002281 // err = dh.groupMgr.AddGroup(ctx, group)
2282 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002283 if err != nil {
2284 errorsList = append(errorsList, err)
2285 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002286 }
2287 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002288 // err = dh.groupMgr.ModifyGroup(ctx, group)
2289 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002290 if err != nil {
2291 errorsList = append(errorsList, err)
2292 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002293 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002294 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002295 // err = dh.groupMgr.DeleteGroup(ctx, group)
2296 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002297 if err != nil {
2298 errorsList = append(errorsList, err)
2299 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002300 }
2301 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002302
2303 return errorsList
2304}
2305
Mahir Gunyela2e68702022-12-07 00:00:42 -08002306// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002307func (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 -07002308
2309 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002310
2311 if dh.getDeviceDeletionInProgressFlag() {
2312 // The device itself is going to be reset as part of deletion. So nothing to be done.
2313 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2314 return nil
2315 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302316 if dh.transitionMap.currentDeviceState != deviceStateUp {
2317 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2318 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2319 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002320 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2321 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2322 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002323 if len(errorsList) > 0 {
2324 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2325 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002326 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002327 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302328}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002329
Mahir Gunyela2e68702022-12-07 00:00:42 -08002330// DisableDevice disables the given device
2331// It marks the following for the given device:
2332// Device-Handler Admin-State : down
2333// Device Port-State: UNKNOWN
2334// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002335func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002336 /* On device disable ,admin state update has to be done prior sending request to agent since
2337 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002338 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002339 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002340 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002341 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002342 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002343 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002344 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002345 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002346 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002347 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302348
2349 dh.discOnus = sync.Map{}
2350 dh.onus = sync.Map{}
2351
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002352 dh.lockDevice.RLock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302353 //stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002354 if dh.isCollectorActive {
2355 dh.stopCollector <- true
2356 }
2357 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302358
Neha Sharma96b7bf22020-06-15 10:37:32 +00002359 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002360 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05302361 //Update device Admin state
2362 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002363
kdarapu1afeceb2020-02-12 01:38:09 -05002364 // 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 -04002365 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002366 DeviceId: cloned.Id,
2367 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2368 OperStatus: voltha.OperStatus_UNKNOWN,
2369 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002370 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002371 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002372 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002373 return nil
2374}
2375
Neha Sharma96b7bf22020-06-15 10:37:32 +00002376func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002377 // Update onu state as unreachable in onu adapter
2378 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302379 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002380
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002381 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002382 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002383 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002384 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 -04002385 }
2386 if onuDevices != nil {
2387 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002388 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002389 DeviceId: onuDevice.Id,
2390 OnuIndication: &onuInd,
2391 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002392 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002393 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002394 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002395 }
2396
2397 }
2398 }
2399
2400}
2401
Mahir Gunyela2e68702022-12-07 00:00:42 -08002402// ReenableDevice re-enables the olt device after disable
2403// It marks the following for the given device:
2404// Device-Handler Admin-State : up
2405// Device Port-State: ACTIVE
2406// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002407func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302408 if dh.Client != nil {
2409 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2410 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2411 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2412 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302413 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302414 } else {
2415 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2416
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302417 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302418
Neha Sharma96b7bf22020-06-15 10:37:32 +00002419 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002420
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002421 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002422 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002423 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002424 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002425 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2426 } else {
2427 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2428 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2429 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002430 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002431 if retError == nil {
2432 //Update the device oper status as ACTIVE
2433 device.OperStatus = voltha.OperStatus_ACTIVE
2434 } else {
2435 //Update the device oper status as FAILED
2436 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002437 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002438 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002439
khenaidoodc2116e2021-10-19 17:33:19 -04002440 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002441 DeviceId: device.Id,
2442 OperStatus: device.OperStatus,
2443 ConnStatus: device.ConnectStatus,
2444 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302445 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002446 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002447 "connect-status": device.ConnectStatus,
2448 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002449 }
kesavand39e0aa32020-01-28 20:58:50 -05002450
Neha Sharma96b7bf22020-06-15 10:37:32 +00002451 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002452
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002453 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002454}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002455
npujarec5762e2020-01-01 14:08:48 +05302456func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002457 var uniID uint32
2458 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002459 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302460 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002461 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002462 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002463 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002464 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2465 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2466 } else {
2467 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2468 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002469 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002470 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002471 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002472 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002473 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002474 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002475 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002476 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002477 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002478 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002479 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002480 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002481 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002482 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002483 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002484 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302485 }
yasin saplibddc2d72022-02-08 13:10:17 +00002486 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2487 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002488 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002489 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302490 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002491 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002492 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002493 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 -03002494 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002495 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002496 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002497 if len(errs) > 0 {
2498 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2499 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2500 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002501 return nil
2502}
2503
Devmalya Paul495b94a2019-08-27 19:42:00 -04002504// 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 +05302505func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002506 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002507 /* Clear the KV store data associated with the all the UNI ports
2508 This clears up flow data and also resource map data for various
2509 other pon resources like alloc_id and gemport_id
2510 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002511
2512 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002513
2514 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002515
Gustavo Silva41af9122022-10-11 11:05:13 -03002516 err := dh.cleanupDeviceResources(ctx)
2517 if err != nil {
2518 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2519 } else {
2520 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2521 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002522
Himani Chawla49a5d562020-11-25 11:53:44 +05302523 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002524 // Stop the Stats collector
2525 if dh.isCollectorActive {
2526 dh.stopCollector <- true
2527 }
2528 // stop the heartbeat check routine
2529 if dh.isHeartbeatCheckActive {
2530 dh.stopHeartbeatCheck <- true
2531 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302532 // Stop the read indication only if it the routine is active
2533 if dh.isReadIndicationRoutineActive {
2534 dh.stopIndications <- true
2535 }
2536 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002537 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002538 //Reset the state
2539 if dh.Client != nil {
2540 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002541 go func() {
2542 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
2543 if err = dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err != nil {
2544 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
2545 }
2546 }()
2547 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002548 }
2549 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002550 // There is no need to update the core about operation status and connection status of the OLT.
2551 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2552 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2553 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002554
khenaidoo7eb2d672021-10-22 19:08:50 -04002555 // Stop the adapter grpc clients for that parent device
2556 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002557 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002558}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002559
2560// StopAllFlowRoutines stops all flow routines
2561func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2562 var wg sync.WaitGroup
2563 wg.Add(1) // for the mcast routine below to finish
2564 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2565 for _, flMgr := range dh.flowMgr {
2566 if flMgr != nil {
2567 wg.Add(1) // for the flow handler routine below to finish
2568 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2569 }
2570 }
2571 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2572 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2573 } else {
2574 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2575 }
2576}
2577
Gustavo Silva41af9122022-10-11 11:05:13 -03002578func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2579 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002580 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302581 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002582 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002583 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002584 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002585 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002586 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2587 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302588 }
2589 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002590 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2591 errs = append(errs, err)
2592 }
2593 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2594 errs = append(errs, err)
2595 }
2596 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2597 errs = append(errs, err)
2598 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002599 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002600 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002601 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002602 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002603 }
2604 // Clean up NNI manager's data
2605 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2606 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002607 }
A R Karthick1f85b802019-10-11 05:06:05 +00002608
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002609 dh.CloseKVClient(ctx)
2610
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002611 // Take one final sweep at cleaning up KV store for the OLT device
2612 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002613 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2614 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002615 }
2616
Devmalya Paul495b94a2019-08-27 19:42:00 -04002617 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302618 dh.onus.Range(func(key interface{}, value interface{}) bool {
2619 dh.onus.Delete(key)
2620 return true
2621 })
2622
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002623 /*Delete discovered ONU map for the device*/
2624 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2625 dh.discOnus.Delete(key)
2626 return true
2627 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002628 if len(errs) > 0 {
2629 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2630 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2631 }
2632 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002633}
2634
Mahir Gunyela2e68702022-12-07 00:00:42 -08002635// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002636func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302637 if dh.Client != nil {
2638 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2639 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2640 }
2641 } else {
2642 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2643
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002644 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302645
Neha Sharma96b7bf22020-06-15 10:37:32 +00002646 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002647 return nil
2648}
2649
David K. Bainbridge794735f2020-02-11 21:01:37 -08002650func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002651 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002652 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002653 "packet-indication": *packetIn,
2654 "device-id": dh.device.Id,
2655 "packet": hex.EncodeToString(packetIn.Pkt),
2656 })
2657 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002658 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2659 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2660 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002661 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002662 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002663 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002664 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002665 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002666 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002667 "logical-port-num": logicalPortNum,
2668 "device-id": dh.device.Id,
2669 "packet": hex.EncodeToString(packetIn.Pkt),
2670 })
2671 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002672
khenaidoodc2116e2021-10-19 17:33:19 -04002673 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002674 DeviceId: dh.device.Id,
2675 Port: logicalPortNum,
2676 Packet: packetIn.Pkt,
2677 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302678 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002679 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302680 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002681 "device-id": dh.device.Id,
2682 "packet": hex.EncodeToString(packetIn.Pkt),
2683 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002684 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002685
Matteo Scandolo92186242020-06-12 10:54:18 -07002686 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002687 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002688 "packet": hex.EncodeToString(packetIn.Pkt),
2689 "device-id": dh.device.Id,
2690 })
2691 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002692 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002693}
2694
Mahir Gunyela2e68702022-12-07 00:00:42 -08002695// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2696func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2697 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2698 if err != nil {
2699 return olterrors.NewErrInvalidValue(log.Fields{
2700 "egress-nni-port": egressPortNo,
2701 "device-id": dh.device.Id,
2702 }, err)
2703 }
2704 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2705
2706 if logger.V(log.DebugLevel) {
2707 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2708 "uplink-pkt": uplinkPkt,
2709 "packet": hex.EncodeToString(packet.Data),
2710 "device-id": dh.device.Id,
2711 })
2712 }
2713
2714 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2715 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2716 "packet": hex.EncodeToString(packet.Data),
2717 "device-id": dh.device.Id,
2718 }, err)
2719 }
2720 return nil
2721}
2722
2723// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2724func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2725 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2726 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2727 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2728 // Do not packet-out lldp packets on uni port.
2729 // ONOS has no clue about uni/nni ports, it just packets out on all
2730 // available ports on the Logical Switch. It should not be interested
2731 // in the UNI links.
2732 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2733 "device-id": dh.device.Id,
2734 })
2735 return nil
2736 }
2737 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2738 if innerEthType == 0x8100 {
2739 // q-in-q 802.1ad or 802.1q double tagged packet.
2740 // slice out the outer tag.
2741 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2742 if logger.V(log.DebugLevel) {
2743 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2744 "packet-data": hex.EncodeToString(packet.Data),
2745 "device-id": dh.device.Id,
2746 })
2747 }
2748 }
2749 }
2750 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2751 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2752 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2753 var gemPortID uint32
2754 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2755 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2756 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2757 }
2758 if err != nil {
2759 // In this case the openolt agent will receive the gemPortID as 0.
2760 // The agent tries to retrieve the gemPortID in this case.
2761 // This may not always succeed at the agent and packetOut may fail.
2762 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2763 "intf-id": intfID,
2764 "onu-id": onuID,
2765 "uni-id": uniID,
2766 "packet": hex.EncodeToString(packet.Data),
2767 "device-id": dh.device.Id,
2768 "error": err,
2769 })
2770 }
2771
2772 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2773 if logger.V(log.DebugLevel) {
2774 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2775 "egress-port-no": egressPortNo,
2776 "intf-id": intfID,
2777 "onu-id": onuID,
2778 "uni-id": uniID,
2779 "gem-port-id": gemPortID,
2780 "packet": hex.EncodeToString(packet.Data),
2781 "device-id": dh.device.Id,
2782 })
2783 }
2784
2785 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2786 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2787 "source": "adapter",
2788 "destination": "onu",
2789 "egress-port-number": egressPortNo,
2790 "intf-id": intfID,
2791 "oni-id": onuID,
2792 "uni-id": uniID,
2793 "gem-port-id": gemPortID,
2794 "packet": hex.EncodeToString(packet.Data),
2795 "device-id": dh.device.Id,
2796 }, err)
2797 }
2798 return nil
2799}
2800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002801// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002802func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002803 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002804 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002805 "device-id": dh.device.Id,
2806 "egress-port-no": egressPortNo,
2807 "pkt-length": len(packet.Data),
2808 "packet": hex.EncodeToString(packet.Data),
2809 })
2810 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002811
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002812 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002813 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002814 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002815 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002816 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002817 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002818 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002819 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302820 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002821 "egressPortType": egressPortType,
2822 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302823 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002824 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002825 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002826 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002827}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002828
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002829func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2830 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002831}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302832
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002833func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002834
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002835 defer func() {
2836 dh.lockDevice.Lock()
2837 dh.isHeartbeatCheckActive = false
2838 dh.lockDevice.Unlock()
2839 }()
2840
2841 dh.lockDevice.Lock()
2842 dh.isHeartbeatCheckActive = true
2843 dh.lockDevice.Unlock()
2844
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302845 // start the heartbeat check towards the OLT.
2846 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302847 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302848
2849 for {
2850 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2851 select {
2852 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002853 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002854 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002855 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302856 if timerCheck == nil {
2857 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002858 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302859 }
2860 } else {
2861 if timerCheck != nil {
2862 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002863 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302864 }
2865 timerCheck = nil
2866 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302867 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2868 if dh.heartbeatSignature == 0 {
2869 // First time the signature will be 0, update the signture to DB when not found.
2870 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2871 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2872 }
2873 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2874
2875 dh.lockDevice.RLock()
2876 // Stop the read indication only if it the routine is active
2877 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2878 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2879 // on next execution of the readIndication routine.
2880 if !dh.isReadIndicationRoutineActive {
2881 // Start reading indications
2882 go func() {
2883 if err = dh.readIndications(ctx); err != nil {
2884 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2885 }
2886 }()
2887 }
2888 dh.lockDevice.RUnlock()
2889
2890 } else {
2891 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2892 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2893 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2894 go dh.updateStateRebooted(ctx)
2895 }
2896
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302897 }
2898 cancel()
2899 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002900 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302901 return
2902 }
2903 }
2904}
2905
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002906func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002907 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002908 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002909 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2910 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2911 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2912 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2913 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002914 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002915 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2916 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002917 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302918
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302919 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002920 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002921 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002922 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002923 DeviceId: dh.device.Id,
2924 OperStatus: voltha.OperStatus_UNKNOWN,
2925 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2926 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002927 _ = 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 -04002928 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302929 /*
2930 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2931 DeviceId: dh.device.Id,
2932 PortTypeFilter: 0,
2933 OperStatus: voltha.OperStatus_UNKNOWN,
2934 }); err != nil {
2935 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2936 }
2937 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002938
2939 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002940 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002941 cloned := proto.Clone(device).(*voltha.Device)
2942 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2943 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2944 dh.device = cloned // update local copy of the device
2945 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002946
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002947 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002948 // Stop the Stats collector
2949 if dh.isCollectorActive {
2950 dh.stopCollector <- true
2951 }
2952 // stop the heartbeat check routine
2953 if dh.isHeartbeatCheckActive {
2954 dh.stopHeartbeatCheck <- true
2955 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002956 // Stop the read indication only if it the routine is active
2957 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2958 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2959 // on next execution of the readIndication routine.
2960 if dh.isReadIndicationRoutineActive {
2961 dh.stopIndications <- true
2962 }
2963 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002964 dh.transitionMap.Handle(ctx, DeviceInit)
2965
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302966 }
2967}
kesavand39e0aa32020-01-28 20:58:50 -05002968
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302969func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2970 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2971 if err != nil || device == nil {
2972 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2973 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2974 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2975 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2976 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2977 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2978 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2979 return
2980 }
Mahir Gunyel701df862023-09-07 16:16:04 -07002981 //Starting the cleanup process
2982 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302983
2984 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2985 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2986 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2987 DeviceId: dh.device.Id,
2988 OperStatus: voltha.OperStatus_REBOOTED,
2989 ConnStatus: voltha.ConnectStatus_REACHABLE,
2990 }); err != nil {
2991 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2992 }
2993
2994 dh.lockDevice.RLock()
2995 // Stop the read indication only if it the routine is active
2996 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2997 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2998 // on next execution of the readIndication routine.
2999 if dh.isReadIndicationRoutineActive {
3000 dh.stopIndications <- true
3001 }
3002 dh.lockDevice.RUnlock()
3003
3004 //raise olt communication failure event
3005 raisedTs := time.Now().Unix()
3006 cloned := proto.Clone(device).(*voltha.Device)
3007 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3008 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3009 dh.device = cloned // update local copy of the device
3010 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3011
Gustavo Silva41af9122022-10-11 11:05:13 -03003012 if err := dh.cleanupDeviceResources(ctx); err != nil {
3013 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3014 } else {
3015 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3016 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003017
3018 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303019 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003020 if dh.isCollectorActive {
3021 dh.stopCollector <- true
3022 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303023 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003024 if dh.isHeartbeatCheckActive {
3025 dh.stopHeartbeatCheck <- true
3026 }
3027 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303028
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003029 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303030
3031 //reset adapter reconcile flag
3032 dh.adapterPreviouslyConnected = false
3033 for {
3034
3035 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3036 if err != nil || childDevices == nil {
3037 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3038 continue
3039 }
3040 if len(childDevices.Items) == 0 {
3041 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3042 break
3043 } else {
3044 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3045 time.Sleep(5 * time.Second)
3046 }
3047
3048 }
Mahir Gunyel701df862023-09-07 16:16:04 -07003049 //Cleanup completed , reset the flag
3050 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303051 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3052 dh.transitionMap.Handle(ctx, DeviceInit)
3053
3054}
3055
kesavand39e0aa32020-01-28 20:58:50 -05003056// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003057func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3058 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3059 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003060}
3061
3062// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3064 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3065 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003066}
3067
Mahir Gunyela2e68702022-12-07 00:00:42 -08003068// 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 +00003069func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3070 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003071 if port.GetType() == voltha.Port_ETHERNET_NNI {
3072 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303074 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303075 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003076 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003077 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003078 }
3079 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003080 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003081 ponIntf := &oop.Interface{IntfId: ponID}
3082 var operStatus voltha.OperStatus_Types
3083 if enablePort {
3084 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303085 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003086
3087 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303088 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003089 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003090 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003091 }
3092 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003093 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003095 } else {
3096 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303097 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003098 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303099 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003100 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003101 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003102 }
3103 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003104 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003105 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003106 }
khenaidoodc2116e2021-10-19 17:33:19 -04003107 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003108 DeviceId: dh.device.Id,
3109 PortType: voltha.Port_PON_OLT,
3110 PortNo: port.PortNo,
3111 OperStatus: operStatus,
3112 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303113 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303114 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003115 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003116 }
3117 return nil
3118}
3119
Mahir Gunyela2e68702022-12-07 00:00:42 -08003120// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003121func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003122 // Disable the port and update the oper_port_status to core
3123 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003124 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003125 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303127 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303128 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003129 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003130 }
3131 }
3132 }
3133 return nil
3134}
3135
Mahir Gunyela2e68702022-12-07 00:00:42 -08003136// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003137func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3138 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3139 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003140 if port.Type == voltha.Port_ETHERNET_NNI {
3141 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003142 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003143 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003144 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003145 }
3146 }
3147 if port.Type == voltha.Port_PON_OLT {
3148 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003149 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003150 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003151 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003152 }
3153 }
3154 }
3155}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003156
3157// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003158func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003159 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003160 if dh.getDeviceDeletionInProgressFlag() {
3161 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3162 // will reboot, so everything will be reset on the pOLT too.
3163 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3164 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3165 return nil
3166 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003167 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003168 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003169
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003170 var sn *oop.SerialNumber
3171 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003172 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303173 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003174 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303175 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003176 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003177 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003178
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003179 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003180 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003181 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003182 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3183 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3184 "device-id": dh.device.Id,
3185 "intf-id": intfID,
3186 "onuID": onuID,
3187 "err": err})
3188 } else {
3189 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003190 // Delete flows from device before schedulers and queue
3191 // Clear flowids for gem cache.
3192 removedFlows := []uint64{}
3193 for _, gem := range onuGem.GemPorts {
3194 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3195 for _, flowID := range flowIDs {
3196 //multiple gem port can have the same flow id
3197 //it is better to send only one flowRemove request to the agent
3198 var alreadyRemoved bool
3199 for _, removedFlowID := range removedFlows {
3200 if removedFlowID == flowID {
3201 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3202 alreadyRemoved = true
3203 break
3204 }
3205 }
3206 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003207 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003208 removedFlows = appendUnique64bit(removedFlows, flowID)
3209 }
3210 }
3211 }
3212 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3213 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003214 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3215 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3216 "device-id": dh.device.Id,
3217 "onu-device": onu,
3218 "err": err})
3219 }
yasin saplibddc2d72022-02-08 13:10:17 +00003220 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003221 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3222 "intf-id": intfID,
3223 "onu-device": onu,
3224 "onu-gem": onuGem,
3225 "err": err})
3226 //Not returning error on cleanup.
3227 }
3228 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05303229
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003230 }
yasin saplibddc2d72022-02-08 13:10:17 +00003231 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003232 dh.onus.Delete(onuKey)
3233 dh.discOnus.Delete(onuSn)
3234
3235 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003236 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303237 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303238 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003239 "onu-id": onuID}, err).Log()
3240 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003241
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003242 return nil
3243}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003244func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3245 flow := &oop.Flow{FlowId: flowID}
3246 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3247 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3248 "device-id": dh.device.Id})
3249 } else {
3250 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3251 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3252 "device-id": dh.device.Id,
3253 "err": err})
3254 }
3255 }
3256}
Girish Gowdracefae192020-03-19 18:14:10 -07003257
3258func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003259 for _, field := range flow_utils.GetOfbFields(flow) {
3260 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003261 return field.GetPort()
3262 }
3263 }
3264 return InvalidPort
3265}
3266
3267func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003268 for _, action := range flow_utils.GetActions(flow) {
3269 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003270 if out := action.GetOutput(); out != nil {
3271 return out.GetPort()
3272 }
3273 }
3274 }
3275 return InvalidPort
3276}
3277
Girish Gowdracefae192020-03-19 18:14:10 -07003278func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3279 inPort := getInPortFromFlow(flow)
3280 outPort := getOutPortFromFlow(flow)
3281
3282 if inPort == InvalidPort || outPort == InvalidPort {
3283 return inPort, outPort
3284 }
3285
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003286 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003287 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003288 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003289 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003290 return uniPort, outPort
3291 }
3292 }
3293 } else {
3294 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003295 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003296 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003297 return inPort, uniPort
3298 }
3299 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003300 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003301 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003302 return uniPort, outPort
3303 }
3304 }
3305 }
3306
3307 return InvalidPort, InvalidPort
3308}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003309
3310func extractOmciTransactionID(omciPkt []byte) uint16 {
3311 if len(omciPkt) > 3 {
3312 d := omciPkt[0:2]
3313 transid := binary.BigEndian.Uint16(d)
3314 return transid
3315 }
3316 return 0
3317}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003318
3319// StoreOnuDevice stores the onu parameters to the local cache.
3320func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3321 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3322 dh.onus.Store(onuKey, onuDevice)
3323}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003324
khenaidoodc2116e2021-10-19 17:33:19 -04003325func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003326 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003327 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003328 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003329 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003330 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003331 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003332 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003333 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3334 return nil, err
3335 }
3336 ID = device.ProxyAddress.GetOnuId()
3337 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3338 valueparam.Onu = &Onu
3339 valueparam.Value = value
3340
3341 // This API is unsupported until agent patch is added
3342 resp.Unsupported = uint32(value)
3343 _ = ctx
3344
3345 // Uncomment this code once agent changes are complete and tests
3346 /*
3347 resp, err = dh.Client.GetValue(ctx, valueparam)
3348 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003349 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003350 return nil, err
3351 }
3352 */
3353
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003354 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 -08003355 return resp, nil
3356}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003357
yasin saplid0566272021-12-21 09:10:30 +00003358func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
3359 // Default to NNI
3360 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003361 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003362 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003363 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003364 }
3365 return intfID
3366}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003367
Mahir Gunyelb0046752021-02-26 13:51:05 -08003368func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
3369 dh.perPonOnuIndicationChannelLock.Lock()
3370 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3371 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003372 return ch.indicationChannel
3373 }
3374 channels := onuIndicationChannels{
3375 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08003376 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003377 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003378 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003379 stopChannel: make(chan struct{}),
3380 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003381 dh.perPonOnuIndicationChannel[intfID] = channels
3382 dh.perPonOnuIndicationChannelLock.Unlock()
3383 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003384 return channels.indicationChannel
3385
3386}
3387
Mahir Gunyelb0046752021-02-26 13:51:05 -08003388func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3389 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3390 dh.perPonOnuIndicationChannelLock.Lock()
3391 defer dh.perPonOnuIndicationChannelLock.Unlock()
3392 for _, v := range dh.perPonOnuIndicationChannel {
3393 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003394 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003395 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003396}
3397
Mahir Gunyelb0046752021-02-26 13:51:05 -08003398func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3399 ind := onuIndicationMsg{
3400 ctx: ctx,
3401 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003402 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003403 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003404 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003405 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003406}
3407
Mahir Gunyelb0046752021-02-26 13:51:05 -08003408func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003409 for {
3410 select {
3411 // process one indication per onu, before proceeding to the next one
3412 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003413 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003414 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003415 "ind": indication})
3416 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003417 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003418 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003419 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3420 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003421 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003422 }
3423 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003424 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003425 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3426 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003427 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003428 }
3429 }
3430 case <-onuChannels.stopChannel:
3431 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3432 close(onuChannels.indicationChannel)
3433 return
3434 }
3435 }
3436}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003437
3438// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3439// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003440func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003441 if dh.getDeviceDeletionInProgressFlag() {
3442 // The device itself is going to be reset as part of deletion. So nothing to be done.
3443 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3444 return nil
3445 }
3446
Girish Gowdra491a9c62021-01-06 16:43:07 -08003447 // Step1 : Fill McastFlowOrGroupControlBlock
3448 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3449 // Step3 : Wait on response channel for response
3450 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003451 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003452 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3453 errChan := make(chan error)
3454 var groupID uint32
3455 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3456 ctx: ctx,
3457 flowOrGroupAction: action,
3458 flow: flow,
3459 group: group,
3460 errChan: &errChan,
3461 }
3462 if flow != nil {
3463 groupID = flow_utils.GetGroup(flow)
3464 } else if group != nil {
3465 groupID = group.Desc.GroupId
3466 } else {
3467 return errors.New("flow-and-group-both-nil")
3468 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003469 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3470 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3471 // Derive the appropriate go routine to handle the request by a simple module operation.
3472 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3473 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3474 // Wait for handler to return error value
3475 err := <-errChan
3476 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3477 return err
3478 }
3479 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3480 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003481}
3482
3483// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003484func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003485 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003486 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003487 // block on the channel to receive an incoming mcast flow/group
3488 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003489 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3490 if mcastFlowOrGroupCb.flow != nil {
3491 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3492 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3493 log.Fields{"device-id": dh.device.Id,
3494 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003495 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3496 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3497 for _, flMgr := range dh.flowMgr {
3498 if flMgr != nil {
3499 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3500 break
3501 }
3502 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003503 // Pass the return value over the return channel
3504 *mcastFlowOrGroupCb.errChan <- err
3505 } else { // flow remove
3506 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3507 log.Fields{"device-id": dh.device.Id,
3508 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003509 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3510 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3511 for _, flMgr := range dh.flowMgr {
3512 if flMgr != nil {
3513 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3514 break
3515 }
3516 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003517 // Pass the return value over the return channel
3518 *mcastFlowOrGroupCb.errChan <- err
3519 }
3520 } else { // mcast group
3521 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3522 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3523 log.Fields{"device-id": dh.device.Id,
3524 "groupToAdd": mcastFlowOrGroupCb.group})
3525 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3526 // Pass the return value over the return channel
3527 *mcastFlowOrGroupCb.errChan <- err
3528 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3529 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3530 log.Fields{"device-id": dh.device.Id,
3531 "groupToModify": mcastFlowOrGroupCb.group})
3532 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3533 // Pass the return value over the return channel
3534 *mcastFlowOrGroupCb.errChan <- err
3535 } else { // group remove
3536 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3537 log.Fields{"device-id": dh.device.Id,
3538 "groupToRemove": mcastFlowOrGroupCb.group})
3539 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3540 // Pass the return value over the return channel
3541 *mcastFlowOrGroupCb.errChan <- err
3542 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003543 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003544 case <-stopHandler:
3545 dh.mcastHandlerRoutineActive[routineIndex] = false
3546 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003547 }
3548 }
3549}
kesavand62126212021-01-12 04:56:06 -05003550
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003551// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003552func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003553 for i, v := range dh.stopMcastHandlerRoutine {
3554 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003555 select {
3556 case v <- true:
3557 case <-time.After(time.Second * 5):
3558 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3559 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003560 }
3561 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003562
3563 if dh.incomingMcastFlowOrGroup != nil {
3564 for k := range dh.incomingMcastFlowOrGroup {
3565 if dh.incomingMcastFlowOrGroup[k] != nil {
3566 dh.incomingMcastFlowOrGroup[k] = nil
3567 }
3568 }
3569 dh.incomingMcastFlowOrGroup = nil
3570 }
3571
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003572 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003573 logger.Debug(ctx, "stopped all mcast handler routines")
3574}
3575
kesavand62126212021-01-12 04:56:06 -05003576func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3577
3578 singleValResp := extension.SingleGetValueResponse{
3579 Response: &extension.GetValueResponse{
3580 Response: &extension.GetValueResponse_PortCoutners{
3581 PortCoutners: &extension.GetOltPortCountersResponse{},
3582 },
3583 },
3584 }
3585
3586 errResp := func(status extension.GetValueResponse_Status,
3587 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3588 return &extension.SingleGetValueResponse{
3589 Response: &extension.GetValueResponse{
3590 Status: status,
3591 ErrReason: reason,
3592 },
3593 }
3594 }
3595
3596 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3597 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3598 //send error response
3599 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3600 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3601 }
3602 statIndChn := make(chan bool, 1)
3603 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3604 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3605 //request openOlt agent to send the the port statistics indication
3606
3607 go func() {
3608 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3609 if err != nil {
3610 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3611 }
3612 }()
3613 select {
3614 case <-statIndChn:
3615 //indication received for ports stats
3616 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3617 case <-time.After(oltPortInfoTimeout * time.Second):
3618 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3619 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3620 case <-ctx.Done():
3621 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3622 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3623 }
3624 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3625 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003626 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003627 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3628 cmnni := dh.portStats.collectNNIMetrics(intfID)
3629 if cmnni == nil {
3630 //TODO define the error reason
3631 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3632 }
3633 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3634 return &singleValResp
3635
3636 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3637 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003638 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003639 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3640 cmpon := dh.portStats.collectPONMetrics(intfID)
3641 if cmpon == nil {
3642 //TODO define the error reason
3643 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3644 }
3645 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3646 return &singleValResp
3647 }
3648 }
3649 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3650}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303651
3652func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3653
3654 singleValResp := extension.SingleGetValueResponse{
3655 Response: &extension.GetValueResponse{
3656 Response: &extension.GetValueResponse_OnuPonCounters{
3657 OnuPonCounters: &extension.GetOnuCountersResponse{},
3658 },
3659 },
3660 }
3661
3662 errResp := func(status extension.GetValueResponse_Status,
3663 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3664 return &extension.SingleGetValueResponse{
3665 Response: &extension.GetValueResponse{
3666 Status: status,
3667 ErrReason: reason,
3668 },
3669 }
3670 }
3671 intfID := onuPonInfo.IntfId
3672 onuID := onuPonInfo.OnuId
3673 onuKey := dh.formOnuKey(intfID, onuID)
3674
3675 if _, ok := dh.onus.Load(onuKey); !ok {
3676 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3677 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3678 }
3679 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3680 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3681 if cmnni == nil {
3682 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3683 }
3684 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3685 return &singleValResp
3686
3687}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003688
nikesh.krishnanc8473432023-06-14 12:14:54 +05303689func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
3690
3691 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3692 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3693 if err != nil {
3694 return nil, err
3695 }
3696 return OnuInfo, nil
3697
3698}
3699
3700func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
3701
3702 Intf := oop.Interface{IntfId: intfID}
3703 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3704 if err != nil {
3705 return nil, err
3706 }
3707 return IntfInfo, nil
3708
3709}
3710
Gamze Abaka85e9a142021-05-26 13:41:39 +00003711func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3712
3713 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3714 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3715 if err != nil {
3716 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3717 return generateSingleGetValueErrorResponse(err)
3718 }
3719 return &extension.SingleGetValueResponse{
3720 Response: &extension.GetValueResponse{
3721 Status: extension.GetValueResponse_OK,
3722 Response: &extension.GetValueResponse_RxPower{
3723 RxPower: &extension.GetRxPowerResponse{
3724 IntfId: rxPowerRequest.IntfId,
3725 OnuId: rxPowerRequest.OnuId,
3726 Status: rxPower.Status,
3727 FailReason: rxPower.FailReason.String(),
3728 RxPower: rxPower.RxPowerMeanDbm,
3729 },
3730 },
3731 },
3732 }
3733}
3734
praneeth nalmas55616d62023-02-06 09:19:18 +05303735func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
3736
3737 errResp := func(status extension.GetValueResponse_Status,
3738 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3739 return &extension.SingleGetValueResponse{
3740 Response: &extension.GetValueResponse{
3741 Status: status,
3742 ErrReason: reason,
3743 },
3744 }
3745 }
3746
3747 resp := extension.SingleGetValueResponse{
3748 Response: &extension.GetValueResponse{
3749 Status: extension.GetValueResponse_OK,
3750 Response: &extension.GetValueResponse_OltRxPower{
3751 OltRxPower: &extension.GetOltRxPowerResponse{},
3752 },
3753 },
3754 }
3755
3756 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3757 portLabel := OltRxPowerRequest.PortLabel
3758 serialNumber := OltRxPowerRequest.OnuSn
3759
3760 portInfo := strings.Split(portLabel, "-")
3761 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3762
3763 if err != nil {
3764 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3765 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3766 }
3767
3768 if portInfo[0] != "pon" {
3769 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3770 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3771 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303772
3773 if serialNumber != "" {
3774
3775 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3776 if onuDev != nil {
3777
3778 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3779 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3780 if err != nil {
3781
3782 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3783 return generateSingleGetValueErrorResponse(err)
3784
3785 }
3786
3787 rxPowerValue := extension.RxPower{}
3788 rxPowerValue.OnuSn = onuDev.serialNumber
3789 rxPowerValue.Status = rxPower.GetStatus()
3790 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3791 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3792
3793 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3794
3795 } else {
3796
3797 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3798 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3799 }
3800
3801 } else {
3802
3803 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303804 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth nalmas55616d62023-02-06 09:19:18 +05303805
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303806 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05303807 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3808 if err != nil {
3809 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3810 } else {
3811
3812 rxPowerValue := extension.RxPower{}
3813 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3814 rxPowerValue.Status = rxPower.GetStatus()
3815 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3816 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3817
3818 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3819 }
3820
3821 }
3822 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3823 return true
3824 })
3825 }
3826 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3827 return &resp
3828}
3829
Gamze Abaka85e9a142021-05-26 13:41:39 +00003830func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3831 errResp := func(status extension.GetValueResponse_Status,
3832 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3833 return &extension.SingleGetValueResponse{
3834 Response: &extension.GetValueResponse{
3835 Status: status,
3836 ErrReason: reason,
3837 },
3838 }
3839 }
3840
3841 if err != nil {
3842 if e, ok := status.FromError(err); ok {
3843 switch e.Code() {
3844 case codes.Internal:
3845 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3846 case codes.DeadlineExceeded:
3847 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3848 case codes.Unimplemented:
3849 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3850 case codes.NotFound:
3851 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3852 }
3853 }
3854 }
3855
3856 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3857}
khenaidoo106c61a2021-08-11 18:05:46 -04003858
3859/*
3860Helper functions to communicate with Core
3861*/
3862
3863func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3864 cClient, err := dh.coreClient.GetCoreServiceClient()
3865 if err != nil || cClient == nil {
3866 return nil, err
3867 }
3868 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3869 defer cancel()
3870 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3871}
3872
khenaidoodc2116e2021-10-19 17:33:19 -04003873func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003874 cClient, err := dh.coreClient.GetCoreServiceClient()
3875 if err != nil || cClient == nil {
3876 return nil, err
3877 }
3878 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3879 defer cancel()
3880 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3881}
3882
khenaidoodc2116e2021-10-19 17:33:19 -04003883func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003884 cClient, err := dh.coreClient.GetCoreServiceClient()
3885 if err != nil || cClient == nil {
3886 return err
3887 }
3888 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3889 defer cancel()
3890 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3891 return err
3892}
3893
3894func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3895 cClient, err := dh.coreClient.GetCoreServiceClient()
3896 if err != nil || cClient == nil {
3897 return nil, err
3898 }
3899 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3900 defer cancel()
3901 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3902}
3903
3904func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3905 cClient, err := dh.coreClient.GetCoreServiceClient()
3906 if err != nil || cClient == nil {
3907 return nil, err
3908 }
3909 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3910 defer cancel()
3911 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3912}
3913
3914func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3915 cClient, err := dh.coreClient.GetCoreServiceClient()
3916 if err != nil || cClient == nil {
3917 return err
3918 }
3919 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3920 defer cancel()
3921 _, err = cClient.DeviceUpdate(subCtx, device)
3922 return err
3923}
3924
khenaidoodc2116e2021-10-19 17:33:19 -04003925func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003926 cClient, err := dh.coreClient.GetCoreServiceClient()
3927 if err != nil || cClient == nil {
3928 return nil, err
3929 }
3930 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3931 defer cancel()
3932 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3933}
3934
khenaidoodc2116e2021-10-19 17:33:19 -04003935func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003936 cClient, err := dh.coreClient.GetCoreServiceClient()
3937 if err != nil || cClient == nil {
3938 return err
3939 }
3940 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3941 defer cancel()
3942 _, err = cClient.SendPacketIn(subCtx, pkt)
3943 return err
3944}
3945
3946func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3947 cClient, err := dh.coreClient.GetCoreServiceClient()
3948 if err != nil || cClient == nil {
3949 return err
3950 }
3951 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3952 defer cancel()
3953 _, err = cClient.PortCreated(subCtx, port)
3954 return err
3955}
3956
khenaidoodc2116e2021-10-19 17:33:19 -04003957func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003958 cClient, err := dh.coreClient.GetCoreServiceClient()
3959 if err != nil || cClient == nil {
3960 return err
3961 }
3962 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3963 defer cancel()
3964 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3965 return err
3966}
3967
khenaidoodc2116e2021-10-19 17:33:19 -04003968func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003969 cClient, err := dh.coreClient.GetCoreServiceClient()
3970 if err != nil || cClient == nil {
3971 return err
3972 }
3973 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3974 defer cancel()
3975 _, err = cClient.PortStateUpdate(subCtx, portState)
3976 return err
3977}
3978
khenaidoodc2116e2021-10-19 17:33:19 -04003979func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003980 cClient, err := dh.coreClient.GetCoreServiceClient()
3981 if err != nil || cClient == nil {
3982 return nil, err
3983 }
3984 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3985 defer cancel()
3986 return cClient.GetDevicePort(subCtx, portFilter)
3987}
3988
nikesh.krishnanc8473432023-06-14 12:14:54 +05303989func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
3990 cClient, err := dh.coreClient.GetCoreServiceClient()
3991 if err != nil || cClient == nil {
3992 return nil, err
3993 }
3994 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3995 defer cancel()
3996 return cClient.GetPorts(subCtx, portFilter)
3997}
3998
khenaidoo106c61a2021-08-11 18:05:46 -04003999/*
4000Helper functions to communicate with child adapter
4001*/
4002
khenaidoodc2116e2021-10-19 17:33:19 -04004003func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004004 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4005 if err != nil || aClient == nil {
4006 return err
4007 }
4008 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4009 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4010 defer cancel()
4011 _, err = aClient.OmciIndication(subCtx, response)
4012 return err
4013}
4014
khenaidoodc2116e2021-10-19 17:33:19 -04004015func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004016 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4017 if err != nil || aClient == nil {
4018 return err
4019 }
4020 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4021 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4022 defer cancel()
4023 _, err = aClient.OnuIndication(subCtx, onuInd)
4024 return err
4025}
4026
khenaidoodc2116e2021-10-19 17:33:19 -04004027func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004028 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4029 if err != nil || aClient == nil {
4030 return err
4031 }
4032 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4033 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4034 defer cancel()
4035 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4036 return err
4037}
4038
khenaidoodc2116e2021-10-19 17:33:19 -04004039func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004040 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4041 if err != nil || aClient == nil {
4042 return err
4043 }
4044 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4045 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4046 defer cancel()
4047 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4048 return err
4049}
4050
khenaidoodc2116e2021-10-19 17:33:19 -04004051func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004052 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4053 if err != nil || aClient == nil {
4054 return err
4055 }
4056 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4057 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4058 defer cancel()
4059 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4060 return err
4061}
4062
4063/*
4064Helper functions for remote communication
4065*/
4066
4067// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4068// supports is deleted
4069func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4070 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4071
4072 dh.lockChildAdapterClients.Lock()
4073 defer dh.lockChildAdapterClients.Unlock()
4074 if _, ok := dh.childAdapterClients[endpoint]; ok {
4075 // Already set
4076 return nil
4077 }
4078
4079 // Setup child's adapter grpc connection
4080 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004081 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4082 dh.cfg.AdapterEndpoint,
4083 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004084 "onu_inter_adapter_service.OnuInterAdapterService",
4085 dh.onuInterAdapterRestarted,
4086 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004087 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4088 return err
4089 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304090 retryCodes := []codes.Code{
4091 codes.Unavailable, // server is currently unavailable
4092 codes.DeadlineExceeded, // deadline for the operation was exceeded
4093 }
4094 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4095 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 -04004096
nikesh.krishnand9812542023-08-01 18:31:39 +05304097 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004098 // Wait until we have a connection to the child adapter.
4099 // Unlimited retries or until context expires
4100 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4101 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4102 for {
4103 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4104 if err == nil && client != nil {
4105 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4106 break
4107 }
4108 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4109 // Backoff
4110 if err = backoff.Backoff(subCtx); err != nil {
4111 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4112 break
4113 }
4114 }
4115 return nil
4116}
4117
khenaidoodc2116e2021-10-19 17:33:19 -04004118func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004119
4120 // First check from cache
4121 dh.lockChildAdapterClients.RLock()
4122 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4123 dh.lockChildAdapterClients.RUnlock()
4124 return cgClient.GetOnuInterAdapterServiceClient()
4125 }
4126 dh.lockChildAdapterClients.RUnlock()
4127
4128 // Set the child connection - can occur on restarts
4129 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4130 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4131 cancel()
4132 if err != nil {
4133 return nil, err
4134 }
4135
4136 // Get the child client now
4137 dh.lockChildAdapterClients.RLock()
4138 defer dh.lockChildAdapterClients.RUnlock()
4139 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4140 return cgClient.GetOnuInterAdapterServiceClient()
4141 }
4142 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4143}
4144
4145func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4146 dh.lockChildAdapterClients.Lock()
4147 defer dh.lockChildAdapterClients.Unlock()
4148 for key, client := range dh.childAdapterClients {
4149 client.Stop(ctx)
4150 delete(dh.childAdapterClients, key)
4151 }
4152}
4153
khenaidooefff76e2021-12-15 16:51:30 -05004154// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4155func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4156 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004157 return nil
4158}
4159
khenaidooefff76e2021-12-15 16:51:30 -05004160// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4161func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4162 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004163 return nil
4164 }
khenaidooefff76e2021-12-15 16:51:30 -05004165 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004166}
Girish Gowdra950326e2021-11-05 12:43:24 -07004167
4168func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4169 dh.lockDevice.Lock()
4170 defer dh.lockDevice.Unlock()
4171 dh.isDeviceDeletionInProgress = flag
4172}
4173
4174func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4175 dh.lockDevice.RLock()
4176 defer dh.lockDevice.RUnlock()
4177 return dh.isDeviceDeletionInProgress
4178}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004179
4180// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4181// Returns false if waiting timed out.
4182func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4183 c := make(chan struct{})
4184 go func() {
4185 defer close(c)
4186 wg.Wait()
4187 }()
4188 select {
4189 case <-c:
4190 return true // completed normally
4191 case <-time.After(timeout):
4192 return false // timed out
4193 }
4194}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304195
4196func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4197 val, err := json.Marshal(signature)
4198 if err != nil {
4199 logger.Error(ctx, "failed-to-marshal")
4200 return
4201 }
4202 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4203 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4204 }
4205}
4206
4207func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4208 var signature uint32
4209
4210 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4211 if er == nil {
4212 if Value != nil {
4213 Val, er := kvstore.ToByte(Value.Value)
4214 if er != nil {
4215 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4216 return signature
4217 }
4218 if er = json.Unmarshal(Val, &signature); er != nil {
4219 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4220 return signature
4221 }
4222 }
4223 }
4224 return signature
4225}