blob: 725aceccfea61511b92d36bc57956473548fc578 [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
Himani Chawla49a5d562020-11-25 11:53:44 +05302516 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002517 // Stop the Stats collector
2518 if dh.isCollectorActive {
2519 dh.stopCollector <- true
2520 }
2521 // stop the heartbeat check routine
2522 if dh.isHeartbeatCheckActive {
2523 dh.stopHeartbeatCheck <- true
2524 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302525 // Stop the read indication only if it the routine is active
2526 if dh.isReadIndicationRoutineActive {
2527 dh.stopIndications <- true
2528 }
2529 dh.lockDevice.RUnlock()
Akash Soni5c76e272024-01-15 04:09:24 +05302530
2531 err := dh.cleanupDeviceResources(ctx)
2532 if err != nil {
2533 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2534 } else {
2535 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2536 }
2537
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002538 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002539 //Reset the state
2540 if dh.Client != nil {
2541 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002542 go func() {
2543 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
2544 if err = dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err != nil {
2545 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
2546 }
2547 }()
2548 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002549 }
2550 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002551 // There is no need to update the core about operation status and connection status of the OLT.
2552 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2553 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2554 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002555
khenaidoo7eb2d672021-10-22 19:08:50 -04002556 // Stop the adapter grpc clients for that parent device
2557 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002558 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002559}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002560
2561// StopAllFlowRoutines stops all flow routines
2562func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2563 var wg sync.WaitGroup
2564 wg.Add(1) // for the mcast routine below to finish
2565 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2566 for _, flMgr := range dh.flowMgr {
2567 if flMgr != nil {
2568 wg.Add(1) // for the flow handler routine below to finish
2569 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2570 }
2571 }
2572 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2573 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2574 } else {
2575 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2576 }
2577}
2578
Gustavo Silva41af9122022-10-11 11:05:13 -03002579func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2580 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002581 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302582 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002583 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002584 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002585 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002586 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002587 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2588 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302589 }
2590 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002591 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2592 errs = append(errs, err)
2593 }
2594 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2595 errs = append(errs, err)
2596 }
2597 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2598 errs = append(errs, err)
2599 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002600 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002601 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002602 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002603 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002604 }
2605 // Clean up NNI manager's data
2606 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2607 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002608 }
A R Karthick1f85b802019-10-11 05:06:05 +00002609
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002610 dh.CloseKVClient(ctx)
2611
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002612 // Take one final sweep at cleaning up KV store for the OLT device
2613 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002614 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2615 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002616 }
2617
Devmalya Paul495b94a2019-08-27 19:42:00 -04002618 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302619 dh.onus.Range(func(key interface{}, value interface{}) bool {
2620 dh.onus.Delete(key)
2621 return true
2622 })
2623
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002624 /*Delete discovered ONU map for the device*/
2625 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2626 dh.discOnus.Delete(key)
2627 return true
2628 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002629 if len(errs) > 0 {
2630 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2631 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2632 }
2633 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002634}
2635
Mahir Gunyela2e68702022-12-07 00:00:42 -08002636// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002637func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302638 if dh.Client != nil {
2639 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2640 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2641 }
2642 } else {
2643 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2644
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002645 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302646
Neha Sharma96b7bf22020-06-15 10:37:32 +00002647 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002648 return nil
2649}
2650
David K. Bainbridge794735f2020-02-11 21:01:37 -08002651func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002652 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002653 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002654 "packet-indication": *packetIn,
2655 "device-id": dh.device.Id,
2656 "packet": hex.EncodeToString(packetIn.Pkt),
2657 })
2658 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002659 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2660 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2661 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002662 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002663 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002664 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002665 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002666 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002667 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002668 "logical-port-num": logicalPortNum,
2669 "device-id": dh.device.Id,
2670 "packet": hex.EncodeToString(packetIn.Pkt),
2671 })
2672 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002673
khenaidoodc2116e2021-10-19 17:33:19 -04002674 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002675 DeviceId: dh.device.Id,
2676 Port: logicalPortNum,
2677 Packet: packetIn.Pkt,
2678 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302679 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002680 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302681 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002682 "device-id": dh.device.Id,
2683 "packet": hex.EncodeToString(packetIn.Pkt),
2684 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002685 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002686
Matteo Scandolo92186242020-06-12 10:54:18 -07002687 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002688 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002689 "packet": hex.EncodeToString(packetIn.Pkt),
2690 "device-id": dh.device.Id,
2691 })
2692 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002693 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002694}
2695
Mahir Gunyela2e68702022-12-07 00:00:42 -08002696// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2697func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2698 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2699 if err != nil {
2700 return olterrors.NewErrInvalidValue(log.Fields{
2701 "egress-nni-port": egressPortNo,
2702 "device-id": dh.device.Id,
2703 }, err)
2704 }
2705 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2706
2707 if logger.V(log.DebugLevel) {
2708 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2709 "uplink-pkt": uplinkPkt,
2710 "packet": hex.EncodeToString(packet.Data),
2711 "device-id": dh.device.Id,
2712 })
2713 }
2714
2715 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2716 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2717 "packet": hex.EncodeToString(packet.Data),
2718 "device-id": dh.device.Id,
2719 }, err)
2720 }
2721 return nil
2722}
2723
2724// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2725func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2726 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2727 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2728 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2729 // Do not packet-out lldp packets on uni port.
2730 // ONOS has no clue about uni/nni ports, it just packets out on all
2731 // available ports on the Logical Switch. It should not be interested
2732 // in the UNI links.
2733 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2734 "device-id": dh.device.Id,
2735 })
2736 return nil
2737 }
2738 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2739 if innerEthType == 0x8100 {
2740 // q-in-q 802.1ad or 802.1q double tagged packet.
2741 // slice out the outer tag.
2742 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2743 if logger.V(log.DebugLevel) {
2744 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2745 "packet-data": hex.EncodeToString(packet.Data),
2746 "device-id": dh.device.Id,
2747 })
2748 }
2749 }
2750 }
2751 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2752 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2753 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2754 var gemPortID uint32
2755 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2756 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2757 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2758 }
2759 if err != nil {
2760 // In this case the openolt agent will receive the gemPortID as 0.
2761 // The agent tries to retrieve the gemPortID in this case.
2762 // This may not always succeed at the agent and packetOut may fail.
2763 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2764 "intf-id": intfID,
2765 "onu-id": onuID,
2766 "uni-id": uniID,
2767 "packet": hex.EncodeToString(packet.Data),
2768 "device-id": dh.device.Id,
2769 "error": err,
2770 })
2771 }
2772
2773 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2774 if logger.V(log.DebugLevel) {
2775 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2776 "egress-port-no": egressPortNo,
2777 "intf-id": intfID,
2778 "onu-id": onuID,
2779 "uni-id": uniID,
2780 "gem-port-id": gemPortID,
2781 "packet": hex.EncodeToString(packet.Data),
2782 "device-id": dh.device.Id,
2783 })
2784 }
2785
2786 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2787 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2788 "source": "adapter",
2789 "destination": "onu",
2790 "egress-port-number": egressPortNo,
2791 "intf-id": intfID,
2792 "oni-id": onuID,
2793 "uni-id": uniID,
2794 "gem-port-id": gemPortID,
2795 "packet": hex.EncodeToString(packet.Data),
2796 "device-id": dh.device.Id,
2797 }, err)
2798 }
2799 return nil
2800}
2801
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002802// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002803func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002804 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002805 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002806 "device-id": dh.device.Id,
2807 "egress-port-no": egressPortNo,
2808 "pkt-length": len(packet.Data),
2809 "packet": hex.EncodeToString(packet.Data),
2810 })
2811 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002812
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002813 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002814 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002815 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002816 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002817 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002818 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002819 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002820 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302821 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002822 "egressPortType": egressPortType,
2823 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302824 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002825 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002826 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002827 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002828}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002829
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002830func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2831 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002832}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302833
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002834func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002835
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002836 defer func() {
2837 dh.lockDevice.Lock()
2838 dh.isHeartbeatCheckActive = false
2839 dh.lockDevice.Unlock()
2840 }()
2841
2842 dh.lockDevice.Lock()
2843 dh.isHeartbeatCheckActive = true
2844 dh.lockDevice.Unlock()
2845
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302846 // start the heartbeat check towards the OLT.
2847 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302848 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302849
2850 for {
2851 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2852 select {
2853 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002854 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002855 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002856 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302857 if timerCheck == nil {
2858 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002859 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302860 }
2861 } else {
2862 if timerCheck != nil {
2863 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002864 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302865 }
2866 timerCheck = nil
2867 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302868 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2869 if dh.heartbeatSignature == 0 {
2870 // First time the signature will be 0, update the signture to DB when not found.
2871 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2872 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2873 }
2874 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2875
2876 dh.lockDevice.RLock()
2877 // Stop the read indication only if it the routine is active
2878 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2879 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2880 // on next execution of the readIndication routine.
2881 if !dh.isReadIndicationRoutineActive {
2882 // Start reading indications
2883 go func() {
2884 if err = dh.readIndications(ctx); err != nil {
2885 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2886 }
2887 }()
2888 }
2889 dh.lockDevice.RUnlock()
2890
2891 } else {
2892 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2893 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2894 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2895 go dh.updateStateRebooted(ctx)
2896 }
2897
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302898 }
2899 cancel()
2900 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002901 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302902 return
2903 }
2904 }
2905}
2906
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002907func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002908 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002909 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002910 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2911 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2912 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2913 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2914 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002915 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002916 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2917 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002918 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302919
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302920 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002921 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002922 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002923 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002924 DeviceId: dh.device.Id,
2925 OperStatus: voltha.OperStatus_UNKNOWN,
2926 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2927 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002928 _ = 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 -04002929 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302930 /*
2931 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2932 DeviceId: dh.device.Id,
2933 PortTypeFilter: 0,
2934 OperStatus: voltha.OperStatus_UNKNOWN,
2935 }); err != nil {
2936 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2937 }
2938 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002939
2940 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002941 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002942 cloned := proto.Clone(device).(*voltha.Device)
2943 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2944 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2945 dh.device = cloned // update local copy of the device
2946 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002947
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002948 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002949 // Stop the Stats collector
2950 if dh.isCollectorActive {
2951 dh.stopCollector <- true
2952 }
2953 // stop the heartbeat check routine
2954 if dh.isHeartbeatCheckActive {
2955 dh.stopHeartbeatCheck <- true
2956 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002957 // Stop the read indication only if it the routine is active
2958 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2959 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2960 // on next execution of the readIndication routine.
2961 if dh.isReadIndicationRoutineActive {
2962 dh.stopIndications <- true
2963 }
2964 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002965 dh.transitionMap.Handle(ctx, DeviceInit)
2966
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302967 }
2968}
kesavand39e0aa32020-01-28 20:58:50 -05002969
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302970func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2971 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2972 if err != nil || device == nil {
2973 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2974 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2975 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2976 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2977 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2978 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2979 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2980 return
2981 }
Mahir Gunyel701df862023-09-07 16:16:04 -07002982 //Starting the cleanup process
2983 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302984
2985 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2986 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2987 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2988 DeviceId: dh.device.Id,
2989 OperStatus: voltha.OperStatus_REBOOTED,
2990 ConnStatus: voltha.ConnectStatus_REACHABLE,
2991 }); err != nil {
2992 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2993 }
2994
2995 dh.lockDevice.RLock()
2996 // Stop the read indication only if it the routine is active
2997 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2998 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2999 // on next execution of the readIndication routine.
3000 if dh.isReadIndicationRoutineActive {
3001 dh.stopIndications <- true
3002 }
3003 dh.lockDevice.RUnlock()
3004
3005 //raise olt communication failure event
3006 raisedTs := time.Now().Unix()
3007 cloned := proto.Clone(device).(*voltha.Device)
3008 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3009 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3010 dh.device = cloned // update local copy of the device
3011 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3012
Gustavo Silva41af9122022-10-11 11:05:13 -03003013 if err := dh.cleanupDeviceResources(ctx); err != nil {
3014 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3015 } else {
3016 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3017 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003018
3019 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303020 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003021 if dh.isCollectorActive {
3022 dh.stopCollector <- true
3023 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303024 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003025 if dh.isHeartbeatCheckActive {
3026 dh.stopHeartbeatCheck <- true
3027 }
3028 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303029
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003030 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303031
3032 //reset adapter reconcile flag
3033 dh.adapterPreviouslyConnected = false
3034 for {
3035
3036 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3037 if err != nil || childDevices == nil {
3038 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3039 continue
3040 }
3041 if len(childDevices.Items) == 0 {
3042 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3043 break
3044 } else {
3045 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3046 time.Sleep(5 * time.Second)
3047 }
3048
3049 }
Mahir Gunyel701df862023-09-07 16:16:04 -07003050 //Cleanup completed , reset the flag
3051 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303052 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3053 dh.transitionMap.Handle(ctx, DeviceInit)
3054
3055}
3056
kesavand39e0aa32020-01-28 20:58:50 -05003057// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3059 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3060 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003061}
3062
3063// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003064func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3065 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3066 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003067}
3068
Mahir Gunyela2e68702022-12-07 00:00:42 -08003069// 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 +00003070func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3071 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003072 if port.GetType() == voltha.Port_ETHERNET_NNI {
3073 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303075 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303076 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003077 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003078 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003079 }
3080 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003081 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003082 ponIntf := &oop.Interface{IntfId: ponID}
3083 var operStatus voltha.OperStatus_Types
3084 if enablePort {
3085 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303086 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003087
3088 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303089 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003090 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003091 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003092 }
3093 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003094 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003095 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003096 } else {
3097 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303098 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003099 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303100 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003101 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003102 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003103 }
3104 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003105 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003107 }
khenaidoodc2116e2021-10-19 17:33:19 -04003108 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003109 DeviceId: dh.device.Id,
3110 PortType: voltha.Port_PON_OLT,
3111 PortNo: port.PortNo,
3112 OperStatus: operStatus,
3113 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303114 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303115 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003116 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003117 }
3118 return nil
3119}
3120
Mahir Gunyela2e68702022-12-07 00:00:42 -08003121// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003122func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003123 // Disable the port and update the oper_port_status to core
3124 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003125 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003126 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003127 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303128 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303129 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003130 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003131 }
3132 }
3133 }
3134 return nil
3135}
3136
Mahir Gunyela2e68702022-12-07 00:00:42 -08003137// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003138func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3139 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3140 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003141 if port.Type == voltha.Port_ETHERNET_NNI {
3142 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003143 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003144 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003145 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003146 }
3147 }
3148 if port.Type == voltha.Port_PON_OLT {
3149 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003150 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003151 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003152 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003153 }
3154 }
3155 }
3156}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003157
3158// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003159func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003160 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003161 if dh.getDeviceDeletionInProgressFlag() {
3162 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3163 // will reboot, so everything will be reset on the pOLT too.
3164 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3165 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3166 return nil
3167 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003168 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003169 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003170
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003171 var sn *oop.SerialNumber
3172 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003173 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303174 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003175 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303176 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003177 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003178 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003179
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003180 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003181 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003182 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003183 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3184 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3185 "device-id": dh.device.Id,
3186 "intf-id": intfID,
3187 "onuID": onuID,
3188 "err": err})
3189 } else {
3190 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003191 // Delete flows from device before schedulers and queue
3192 // Clear flowids for gem cache.
3193 removedFlows := []uint64{}
3194 for _, gem := range onuGem.GemPorts {
3195 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3196 for _, flowID := range flowIDs {
3197 //multiple gem port can have the same flow id
3198 //it is better to send only one flowRemove request to the agent
3199 var alreadyRemoved bool
3200 for _, removedFlowID := range removedFlows {
3201 if removedFlowID == flowID {
3202 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3203 alreadyRemoved = true
3204 break
3205 }
3206 }
3207 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003208 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003209 removedFlows = appendUnique64bit(removedFlows, flowID)
3210 }
3211 }
3212 }
3213 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3214 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003215 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3216 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3217 "device-id": dh.device.Id,
3218 "onu-device": onu,
3219 "err": err})
3220 }
yasin saplibddc2d72022-02-08 13:10:17 +00003221 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003222 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3223 "intf-id": intfID,
3224 "onu-device": onu,
3225 "onu-gem": onuGem,
3226 "err": err})
3227 //Not returning error on cleanup.
3228 }
3229 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05303230
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003231 }
yasin saplibddc2d72022-02-08 13:10:17 +00003232 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003233 dh.onus.Delete(onuKey)
3234 dh.discOnus.Delete(onuSn)
3235
3236 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003237 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303238 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303239 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003240 "onu-id": onuID}, err).Log()
3241 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003242
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003243 return nil
3244}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003245func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3246 flow := &oop.Flow{FlowId: flowID}
3247 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3248 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3249 "device-id": dh.device.Id})
3250 } else {
3251 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3252 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3253 "device-id": dh.device.Id,
3254 "err": err})
3255 }
3256 }
3257}
Girish Gowdracefae192020-03-19 18:14:10 -07003258
3259func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003260 for _, field := range flow_utils.GetOfbFields(flow) {
3261 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003262 return field.GetPort()
3263 }
3264 }
3265 return InvalidPort
3266}
3267
3268func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003269 for _, action := range flow_utils.GetActions(flow) {
3270 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003271 if out := action.GetOutput(); out != nil {
3272 return out.GetPort()
3273 }
3274 }
3275 }
3276 return InvalidPort
3277}
3278
Girish Gowdracefae192020-03-19 18:14:10 -07003279func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3280 inPort := getInPortFromFlow(flow)
3281 outPort := getOutPortFromFlow(flow)
3282
3283 if inPort == InvalidPort || outPort == InvalidPort {
3284 return inPort, outPort
3285 }
3286
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003287 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003288 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003289 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003290 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003291 return uniPort, outPort
3292 }
3293 }
3294 } else {
3295 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003296 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003297 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003298 return inPort, uniPort
3299 }
3300 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003301 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003302 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003303 return uniPort, outPort
3304 }
3305 }
3306 }
3307
3308 return InvalidPort, InvalidPort
3309}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003310
3311func extractOmciTransactionID(omciPkt []byte) uint16 {
3312 if len(omciPkt) > 3 {
3313 d := omciPkt[0:2]
3314 transid := binary.BigEndian.Uint16(d)
3315 return transid
3316 }
3317 return 0
3318}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003319
3320// StoreOnuDevice stores the onu parameters to the local cache.
3321func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3322 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3323 dh.onus.Store(onuKey, onuDevice)
3324}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003325
khenaidoodc2116e2021-10-19 17:33:19 -04003326func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003327 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003328 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003329 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003330 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003331 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003332 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003333 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003334 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3335 return nil, err
3336 }
3337 ID = device.ProxyAddress.GetOnuId()
3338 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3339 valueparam.Onu = &Onu
3340 valueparam.Value = value
3341
3342 // This API is unsupported until agent patch is added
3343 resp.Unsupported = uint32(value)
3344 _ = ctx
3345
3346 // Uncomment this code once agent changes are complete and tests
3347 /*
3348 resp, err = dh.Client.GetValue(ctx, valueparam)
3349 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003350 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003351 return nil, err
3352 }
3353 */
3354
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003355 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 -08003356 return resp, nil
3357}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003358
yasin saplid0566272021-12-21 09:10:30 +00003359func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
3360 // Default to NNI
3361 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003362 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003363 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003364 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003365 }
3366 return intfID
3367}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003368
Mahir Gunyelb0046752021-02-26 13:51:05 -08003369func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
3370 dh.perPonOnuIndicationChannelLock.Lock()
3371 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3372 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003373 return ch.indicationChannel
3374 }
3375 channels := onuIndicationChannels{
3376 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08003377 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003378 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003379 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003380 stopChannel: make(chan struct{}),
3381 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003382 dh.perPonOnuIndicationChannel[intfID] = channels
3383 dh.perPonOnuIndicationChannelLock.Unlock()
3384 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003385 return channels.indicationChannel
3386
3387}
3388
Mahir Gunyelb0046752021-02-26 13:51:05 -08003389func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3390 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3391 dh.perPonOnuIndicationChannelLock.Lock()
3392 defer dh.perPonOnuIndicationChannelLock.Unlock()
3393 for _, v := range dh.perPonOnuIndicationChannel {
3394 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003395 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003396 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003397}
3398
Mahir Gunyelb0046752021-02-26 13:51:05 -08003399func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3400 ind := onuIndicationMsg{
3401 ctx: ctx,
3402 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003403 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003404 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003405 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003406 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003407}
3408
Mahir Gunyelb0046752021-02-26 13:51:05 -08003409func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003410 for {
3411 select {
3412 // process one indication per onu, before proceeding to the next one
3413 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003414 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003415 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003416 "ind": indication})
3417 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003418 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003419 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003420 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3421 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003422 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003423 }
3424 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003425 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003426 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3427 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003428 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003429 }
3430 }
3431 case <-onuChannels.stopChannel:
3432 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3433 close(onuChannels.indicationChannel)
3434 return
3435 }
3436 }
3437}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003438
3439// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3440// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003441func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003442 if dh.getDeviceDeletionInProgressFlag() {
3443 // The device itself is going to be reset as part of deletion. So nothing to be done.
3444 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3445 return nil
3446 }
3447
Girish Gowdra491a9c62021-01-06 16:43:07 -08003448 // Step1 : Fill McastFlowOrGroupControlBlock
3449 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3450 // Step3 : Wait on response channel for response
3451 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003452 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003453 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3454 errChan := make(chan error)
3455 var groupID uint32
3456 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3457 ctx: ctx,
3458 flowOrGroupAction: action,
3459 flow: flow,
3460 group: group,
3461 errChan: &errChan,
3462 }
3463 if flow != nil {
3464 groupID = flow_utils.GetGroup(flow)
3465 } else if group != nil {
3466 groupID = group.Desc.GroupId
3467 } else {
3468 return errors.New("flow-and-group-both-nil")
3469 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003470 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3471 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3472 // Derive the appropriate go routine to handle the request by a simple module operation.
3473 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3474 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3475 // Wait for handler to return error value
3476 err := <-errChan
3477 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3478 return err
3479 }
3480 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3481 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003482}
3483
3484// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003485func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003486 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003487 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003488 // block on the channel to receive an incoming mcast flow/group
3489 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003490 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3491 if mcastFlowOrGroupCb.flow != nil {
3492 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3493 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3494 log.Fields{"device-id": dh.device.Id,
3495 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003496 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3497 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3498 for _, flMgr := range dh.flowMgr {
3499 if flMgr != nil {
3500 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3501 break
3502 }
3503 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003504 // Pass the return value over the return channel
3505 *mcastFlowOrGroupCb.errChan <- err
3506 } else { // flow remove
3507 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3508 log.Fields{"device-id": dh.device.Id,
3509 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003510 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3511 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3512 for _, flMgr := range dh.flowMgr {
3513 if flMgr != nil {
3514 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3515 break
3516 }
3517 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003518 // Pass the return value over the return channel
3519 *mcastFlowOrGroupCb.errChan <- err
3520 }
3521 } else { // mcast group
3522 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3523 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3524 log.Fields{"device-id": dh.device.Id,
3525 "groupToAdd": mcastFlowOrGroupCb.group})
3526 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3527 // Pass the return value over the return channel
3528 *mcastFlowOrGroupCb.errChan <- err
3529 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3530 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3531 log.Fields{"device-id": dh.device.Id,
3532 "groupToModify": mcastFlowOrGroupCb.group})
3533 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3534 // Pass the return value over the return channel
3535 *mcastFlowOrGroupCb.errChan <- err
3536 } else { // group remove
3537 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3538 log.Fields{"device-id": dh.device.Id,
3539 "groupToRemove": mcastFlowOrGroupCb.group})
3540 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3541 // Pass the return value over the return channel
3542 *mcastFlowOrGroupCb.errChan <- err
3543 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003544 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003545 case <-stopHandler:
3546 dh.mcastHandlerRoutineActive[routineIndex] = false
3547 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003548 }
3549 }
3550}
kesavand62126212021-01-12 04:56:06 -05003551
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003552// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003553func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003554 for i, v := range dh.stopMcastHandlerRoutine {
3555 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003556 select {
3557 case v <- true:
3558 case <-time.After(time.Second * 5):
3559 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3560 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003561 }
3562 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003563
3564 if dh.incomingMcastFlowOrGroup != nil {
3565 for k := range dh.incomingMcastFlowOrGroup {
3566 if dh.incomingMcastFlowOrGroup[k] != nil {
3567 dh.incomingMcastFlowOrGroup[k] = nil
3568 }
3569 }
3570 dh.incomingMcastFlowOrGroup = nil
3571 }
3572
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003573 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003574 logger.Debug(ctx, "stopped all mcast handler routines")
3575}
3576
kesavand62126212021-01-12 04:56:06 -05003577func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3578
3579 singleValResp := extension.SingleGetValueResponse{
3580 Response: &extension.GetValueResponse{
3581 Response: &extension.GetValueResponse_PortCoutners{
3582 PortCoutners: &extension.GetOltPortCountersResponse{},
3583 },
3584 },
3585 }
3586
3587 errResp := func(status extension.GetValueResponse_Status,
3588 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3589 return &extension.SingleGetValueResponse{
3590 Response: &extension.GetValueResponse{
3591 Status: status,
3592 ErrReason: reason,
3593 },
3594 }
3595 }
3596
3597 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3598 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3599 //send error response
3600 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3601 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3602 }
3603 statIndChn := make(chan bool, 1)
3604 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3605 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3606 //request openOlt agent to send the the port statistics indication
3607
3608 go func() {
3609 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3610 if err != nil {
3611 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3612 }
3613 }()
3614 select {
3615 case <-statIndChn:
3616 //indication received for ports stats
3617 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3618 case <-time.After(oltPortInfoTimeout * time.Second):
3619 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3620 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3621 case <-ctx.Done():
3622 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3623 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3624 }
3625 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3626 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003627 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003628 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3629 cmnni := dh.portStats.collectNNIMetrics(intfID)
3630 if cmnni == nil {
3631 //TODO define the error reason
3632 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3633 }
3634 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3635 return &singleValResp
3636
3637 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3638 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003639 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003640 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3641 cmpon := dh.portStats.collectPONMetrics(intfID)
3642 if cmpon == nil {
3643 //TODO define the error reason
3644 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3645 }
3646 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3647 return &singleValResp
3648 }
3649 }
3650 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3651}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303652
Akash Soni3bcf5e02024-12-03 08:01:48 +05303653func (dh *DeviceHandler) getOltOffloadStats(ctx context.Context, oltPortInfo *extension.GetOffloadedAppsStatisticsRequest) *extension.SingleGetValueResponse {
3654
3655 singleValResp := extension.SingleGetValueResponse{
3656 Response: &extension.GetValueResponse{
3657 Status: extension.GetValueResponse_OK,
3658 Response: &extension.GetValueResponse_OffloadedAppsStats{
3659 OffloadedAppsStats: &extension.GetOffloadedAppsStatisticsResponse{},
3660 },
3661 },
3662 }
3663
3664 return &singleValResp
3665}
3666
3667func (dh *DeviceHandler) setOltOffloadStats(ctx context.Context, congig *extension.AppOffloadConfig) *extension.SingleSetValueResponse {
3668
3669 singleValResp := extension.SingleSetValueResponse{
3670 Response: &extension.SetValueResponse{
3671 Status: extension.SetValueResponse_OK,
3672 },
3673 }
3674
3675 return &singleValResp
3676}
3677
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303678func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3679
3680 singleValResp := extension.SingleGetValueResponse{
3681 Response: &extension.GetValueResponse{
3682 Response: &extension.GetValueResponse_OnuPonCounters{
3683 OnuPonCounters: &extension.GetOnuCountersResponse{},
3684 },
3685 },
3686 }
3687
3688 errResp := func(status extension.GetValueResponse_Status,
3689 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3690 return &extension.SingleGetValueResponse{
3691 Response: &extension.GetValueResponse{
3692 Status: status,
3693 ErrReason: reason,
3694 },
3695 }
3696 }
3697 intfID := onuPonInfo.IntfId
3698 onuID := onuPonInfo.OnuId
3699 onuKey := dh.formOnuKey(intfID, onuID)
3700
3701 if _, ok := dh.onus.Load(onuKey); !ok {
3702 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3703 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3704 }
3705 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3706 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3707 if cmnni == nil {
3708 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3709 }
3710 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3711 return &singleValResp
3712
3713}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003714
nikesh.krishnanc8473432023-06-14 12:14:54 +05303715func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
3716
3717 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3718 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3719 if err != nil {
3720 return nil, err
3721 }
3722 return OnuInfo, nil
3723
3724}
3725
3726func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
3727
3728 Intf := oop.Interface{IntfId: intfID}
3729 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3730 if err != nil {
3731 return nil, err
3732 }
3733 return IntfInfo, nil
3734
3735}
3736
Gamze Abaka85e9a142021-05-26 13:41:39 +00003737func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3738
3739 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3740 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3741 if err != nil {
3742 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3743 return generateSingleGetValueErrorResponse(err)
3744 }
3745 return &extension.SingleGetValueResponse{
3746 Response: &extension.GetValueResponse{
3747 Status: extension.GetValueResponse_OK,
3748 Response: &extension.GetValueResponse_RxPower{
3749 RxPower: &extension.GetRxPowerResponse{
3750 IntfId: rxPowerRequest.IntfId,
3751 OnuId: rxPowerRequest.OnuId,
3752 Status: rxPower.Status,
3753 FailReason: rxPower.FailReason.String(),
3754 RxPower: rxPower.RxPowerMeanDbm,
3755 },
3756 },
3757 },
3758 }
3759}
3760
praneeth nalmas55616d62023-02-06 09:19:18 +05303761func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
3762
3763 errResp := func(status extension.GetValueResponse_Status,
3764 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3765 return &extension.SingleGetValueResponse{
3766 Response: &extension.GetValueResponse{
3767 Status: status,
3768 ErrReason: reason,
3769 },
3770 }
3771 }
3772
3773 resp := extension.SingleGetValueResponse{
3774 Response: &extension.GetValueResponse{
3775 Status: extension.GetValueResponse_OK,
3776 Response: &extension.GetValueResponse_OltRxPower{
3777 OltRxPower: &extension.GetOltRxPowerResponse{},
3778 },
3779 },
3780 }
3781
3782 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3783 portLabel := OltRxPowerRequest.PortLabel
3784 serialNumber := OltRxPowerRequest.OnuSn
3785
3786 portInfo := strings.Split(portLabel, "-")
3787 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3788
3789 if err != nil {
3790 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3791 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3792 }
3793
3794 if portInfo[0] != "pon" {
3795 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3796 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3797 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303798
3799 if serialNumber != "" {
3800
3801 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3802 if onuDev != nil {
3803
3804 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3805 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3806 if err != nil {
3807
3808 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3809 return generateSingleGetValueErrorResponse(err)
3810
3811 }
3812
3813 rxPowerValue := extension.RxPower{}
3814 rxPowerValue.OnuSn = onuDev.serialNumber
3815 rxPowerValue.Status = rxPower.GetStatus()
3816 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3817 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3818
3819 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3820
3821 } else {
3822
3823 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3824 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3825 }
3826
3827 } else {
3828
3829 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303830 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth nalmas55616d62023-02-06 09:19:18 +05303831
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303832 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05303833 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3834 if err != nil {
3835 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3836 } else {
3837
3838 rxPowerValue := extension.RxPower{}
3839 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3840 rxPowerValue.Status = rxPower.GetStatus()
3841 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3842 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3843
3844 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3845 }
3846
3847 }
3848 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3849 return true
3850 })
3851 }
3852 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3853 return &resp
3854}
3855
Gamze Abaka85e9a142021-05-26 13:41:39 +00003856func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3857 errResp := func(status extension.GetValueResponse_Status,
3858 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3859 return &extension.SingleGetValueResponse{
3860 Response: &extension.GetValueResponse{
3861 Status: status,
3862 ErrReason: reason,
3863 },
3864 }
3865 }
3866
3867 if err != nil {
3868 if e, ok := status.FromError(err); ok {
3869 switch e.Code() {
3870 case codes.Internal:
3871 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3872 case codes.DeadlineExceeded:
3873 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3874 case codes.Unimplemented:
3875 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3876 case codes.NotFound:
3877 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3878 }
3879 }
3880 }
3881
3882 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3883}
khenaidoo106c61a2021-08-11 18:05:46 -04003884
3885/*
3886Helper functions to communicate with Core
3887*/
3888
3889func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3890 cClient, err := dh.coreClient.GetCoreServiceClient()
3891 if err != nil || cClient == nil {
3892 return nil, err
3893 }
3894 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3895 defer cancel()
3896 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3897}
3898
khenaidoodc2116e2021-10-19 17:33:19 -04003899func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003900 cClient, err := dh.coreClient.GetCoreServiceClient()
3901 if err != nil || cClient == nil {
3902 return nil, err
3903 }
3904 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3905 defer cancel()
3906 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3907}
3908
khenaidoodc2116e2021-10-19 17:33:19 -04003909func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003910 cClient, err := dh.coreClient.GetCoreServiceClient()
3911 if err != nil || cClient == nil {
3912 return err
3913 }
3914 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3915 defer cancel()
3916 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3917 return err
3918}
3919
3920func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3921 cClient, err := dh.coreClient.GetCoreServiceClient()
3922 if err != nil || cClient == nil {
3923 return nil, err
3924 }
3925 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3926 defer cancel()
3927 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3928}
3929
3930func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3931 cClient, err := dh.coreClient.GetCoreServiceClient()
3932 if err != nil || cClient == nil {
3933 return nil, err
3934 }
3935 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3936 defer cancel()
3937 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3938}
3939
3940func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3941 cClient, err := dh.coreClient.GetCoreServiceClient()
3942 if err != nil || cClient == nil {
3943 return err
3944 }
3945 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3946 defer cancel()
3947 _, err = cClient.DeviceUpdate(subCtx, device)
3948 return err
3949}
3950
khenaidoodc2116e2021-10-19 17:33:19 -04003951func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003952 cClient, err := dh.coreClient.GetCoreServiceClient()
3953 if err != nil || cClient == nil {
3954 return nil, err
3955 }
3956 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3957 defer cancel()
3958 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3959}
3960
khenaidoodc2116e2021-10-19 17:33:19 -04003961func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003962 cClient, err := dh.coreClient.GetCoreServiceClient()
3963 if err != nil || cClient == nil {
3964 return err
3965 }
3966 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3967 defer cancel()
3968 _, err = cClient.SendPacketIn(subCtx, pkt)
3969 return err
3970}
3971
3972func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3973 cClient, err := dh.coreClient.GetCoreServiceClient()
3974 if err != nil || cClient == nil {
3975 return err
3976 }
3977 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3978 defer cancel()
3979 _, err = cClient.PortCreated(subCtx, port)
3980 return err
3981}
3982
khenaidoodc2116e2021-10-19 17:33:19 -04003983func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003984 cClient, err := dh.coreClient.GetCoreServiceClient()
3985 if err != nil || cClient == nil {
3986 return err
3987 }
3988 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3989 defer cancel()
3990 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3991 return err
3992}
3993
khenaidoodc2116e2021-10-19 17:33:19 -04003994func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003995 cClient, err := dh.coreClient.GetCoreServiceClient()
3996 if err != nil || cClient == nil {
3997 return err
3998 }
3999 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4000 defer cancel()
4001 _, err = cClient.PortStateUpdate(subCtx, portState)
4002 return err
4003}
4004
khenaidoodc2116e2021-10-19 17:33:19 -04004005func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004006 cClient, err := dh.coreClient.GetCoreServiceClient()
4007 if err != nil || cClient == nil {
4008 return nil, err
4009 }
4010 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4011 defer cancel()
4012 return cClient.GetDevicePort(subCtx, portFilter)
4013}
4014
nikesh.krishnanc8473432023-06-14 12:14:54 +05304015func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
4016 cClient, err := dh.coreClient.GetCoreServiceClient()
4017 if err != nil || cClient == nil {
4018 return nil, err
4019 }
4020 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4021 defer cancel()
4022 return cClient.GetPorts(subCtx, portFilter)
4023}
4024
khenaidoo106c61a2021-08-11 18:05:46 -04004025/*
4026Helper functions to communicate with child adapter
4027*/
4028
khenaidoodc2116e2021-10-19 17:33:19 -04004029func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004030 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4031 if err != nil || aClient == nil {
4032 return err
4033 }
4034 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4035 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4036 defer cancel()
4037 _, err = aClient.OmciIndication(subCtx, response)
4038 return err
4039}
4040
khenaidoodc2116e2021-10-19 17:33:19 -04004041func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004042 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4043 if err != nil || aClient == nil {
4044 return err
4045 }
4046 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4047 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4048 defer cancel()
4049 _, err = aClient.OnuIndication(subCtx, onuInd)
4050 return err
4051}
4052
khenaidoodc2116e2021-10-19 17:33:19 -04004053func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004054 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4055 if err != nil || aClient == nil {
4056 return err
4057 }
4058 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4059 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4060 defer cancel()
4061 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4062 return err
4063}
4064
khenaidoodc2116e2021-10-19 17:33:19 -04004065func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004066 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4067 if err != nil || aClient == nil {
4068 return err
4069 }
4070 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4071 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4072 defer cancel()
4073 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4074 return err
4075}
4076
khenaidoodc2116e2021-10-19 17:33:19 -04004077func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004078 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4079 if err != nil || aClient == nil {
4080 return err
4081 }
4082 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4083 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4084 defer cancel()
4085 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4086 return err
4087}
4088
4089/*
4090Helper functions for remote communication
4091*/
4092
4093// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4094// supports is deleted
4095func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4096 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4097
4098 dh.lockChildAdapterClients.Lock()
4099 defer dh.lockChildAdapterClients.Unlock()
4100 if _, ok := dh.childAdapterClients[endpoint]; ok {
4101 // Already set
4102 return nil
4103 }
4104
4105 // Setup child's adapter grpc connection
4106 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004107 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4108 dh.cfg.AdapterEndpoint,
4109 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004110 "onu_inter_adapter_service.OnuInterAdapterService",
4111 dh.onuInterAdapterRestarted,
4112 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004113 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4114 return err
4115 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304116 retryCodes := []codes.Code{
4117 codes.Unavailable, // server is currently unavailable
4118 codes.DeadlineExceeded, // deadline for the operation was exceeded
4119 }
4120 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4121 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 -04004122
nikesh.krishnand9812542023-08-01 18:31:39 +05304123 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004124 // Wait until we have a connection to the child adapter.
4125 // Unlimited retries or until context expires
4126 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4127 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4128 for {
4129 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4130 if err == nil && client != nil {
4131 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4132 break
4133 }
4134 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4135 // Backoff
4136 if err = backoff.Backoff(subCtx); err != nil {
4137 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4138 break
4139 }
4140 }
4141 return nil
4142}
4143
khenaidoodc2116e2021-10-19 17:33:19 -04004144func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004145
4146 // First check from cache
4147 dh.lockChildAdapterClients.RLock()
4148 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4149 dh.lockChildAdapterClients.RUnlock()
4150 return cgClient.GetOnuInterAdapterServiceClient()
4151 }
4152 dh.lockChildAdapterClients.RUnlock()
4153
4154 // Set the child connection - can occur on restarts
4155 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4156 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4157 cancel()
4158 if err != nil {
4159 return nil, err
4160 }
4161
4162 // Get the child client now
4163 dh.lockChildAdapterClients.RLock()
4164 defer dh.lockChildAdapterClients.RUnlock()
4165 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4166 return cgClient.GetOnuInterAdapterServiceClient()
4167 }
4168 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4169}
4170
4171func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4172 dh.lockChildAdapterClients.Lock()
4173 defer dh.lockChildAdapterClients.Unlock()
4174 for key, client := range dh.childAdapterClients {
4175 client.Stop(ctx)
4176 delete(dh.childAdapterClients, key)
4177 }
4178}
4179
khenaidooefff76e2021-12-15 16:51:30 -05004180// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4181func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4182 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004183 return nil
4184}
4185
khenaidooefff76e2021-12-15 16:51:30 -05004186// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4187func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4188 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004189 return nil
4190 }
khenaidooefff76e2021-12-15 16:51:30 -05004191 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004192}
Girish Gowdra950326e2021-11-05 12:43:24 -07004193
4194func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4195 dh.lockDevice.Lock()
4196 defer dh.lockDevice.Unlock()
4197 dh.isDeviceDeletionInProgress = flag
4198}
4199
4200func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4201 dh.lockDevice.RLock()
4202 defer dh.lockDevice.RUnlock()
4203 return dh.isDeviceDeletionInProgress
4204}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004205
4206// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4207// Returns false if waiting timed out.
4208func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4209 c := make(chan struct{})
4210 go func() {
4211 defer close(c)
4212 wg.Wait()
4213 }()
4214 select {
4215 case <-c:
4216 return true // completed normally
4217 case <-time.After(timeout):
4218 return false // timed out
4219 }
4220}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304221
4222func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4223 val, err := json.Marshal(signature)
4224 if err != nil {
4225 logger.Error(ctx, "failed-to-marshal")
4226 return
4227 }
4228 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4229 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4230 }
4231}
4232
4233func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4234 var signature uint32
4235
4236 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4237 if er == nil {
4238 if Value != nil {
4239 Val, er := kvstore.ToByte(Value.Value)
4240 if er != nil {
4241 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4242 return signature
4243 }
4244 if er = json.Unmarshal(Val, &signature); er != nil {
4245 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4246 return signature
4247 }
4248 }
4249 }
4250 return signature
4251}