blob: e46999c9b439c1b407d82b348b42f99c60881641 [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)
247 }
248 return nil, errors.New("unsupported-kv-store")
249}
250
251// SetKVClient sets the KV client and return a kv backend
252func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
253 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
254 if err != nil {
255 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
256 return nil
257 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530258 kvbackend := &db.Backend{
259 Client: kvClient,
260 StoreType: backend,
261 Address: addr,
262 Timeout: rsrcMgr.KvstoreTimeout,
263 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
264
265 return kvbackend
266}
267
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000268// CloseKVClient closes open KV clients
269func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
270 if dh.resourceMgr != nil {
271 for _, rscMgr := range dh.resourceMgr {
272 if rscMgr != nil {
273 rscMgr.CloseKVClient(ctx)
274 }
275 }
276 }
277 if dh.flowMgr != nil {
278 for _, flMgr := range dh.flowMgr {
279 if flMgr != nil {
280 flMgr.CloseKVClient(ctx)
281 }
282 }
283 }
284}
285
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530286// start save the device to the data model
287func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700288 dh.lockDevice.Lock()
289 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000290 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700291 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000292 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530293}
294
khenaidooefff76e2021-12-15 16:51:30 -0500295// Stop stops the device handler
296func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700297 dh.lockDevice.Lock()
298 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000299 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500300 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400301
khenaidooefff76e2021-12-15 16:51:30 -0500302 // Delete (which will stop also) all grpc connections to the child adapters
303 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000304 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530305}
306
ssiddiqui04386ee2021-08-23 21:58:25 +0530307func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
308 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
309 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
310 if pooledIntfID == intfID {
311 return resourceRanges.GetTechnology()
312 }
313 }
314 }
315 return ""
316}
317
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400318func macifyIP(ip net.IP) string {
319 if len(ip) > 0 {
320 oct1 := strconv.FormatInt(int64(ip[12]), 16)
321 oct2 := strconv.FormatInt(int64(ip[13]), 16)
322 oct3 := strconv.FormatInt(int64(ip[14]), 16)
323 oct4 := strconv.FormatInt(int64(ip[15]), 16)
324 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
325 }
326 return ""
327}
328
Neha Sharma96b7bf22020-06-15 10:37:32 +0000329func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400330 var genmac string
331 var addr net.IP
332 var ips []string
333 var err error
334
Neha Sharma96b7bf22020-06-15 10:37:32 +0000335 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400336
337 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000338 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400339
340 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000341 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400342 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000343 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400344 }
345 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000346 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530347 log.Fields{"host": ips[0],
348 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400349 return genmac, nil
350 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000351 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400352 }
353
354 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530356 log.Fields{"host": host,
357 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400358 return genmac, nil
359}
360
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530361func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700362 slist := strings.Split(mac, ":")
363 result := make([]uint32, len(slist))
364 var err error
365 var tmp int64
366 for index, val := range slist {
367 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
368 return []uint32{1, 2, 3, 4, 5, 6}
369 }
370 result[index] = uint32(tmp)
371 }
372 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530373}
374
Mahir Gunyela2e68702022-12-07 00:00:42 -0800375// 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 -0800376func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530377
David K. Bainbridge794735f2020-02-11 21:01:37 -0800378 switch portType {
379 case voltha.Port_ETHERNET_NNI:
380 return fmt.Sprintf("nni-%d", portNum), nil
381 case voltha.Port_PON_OLT:
382 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700383 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800384
Girish Kumarf26e4882020-03-05 06:49:10 +0000385 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530386}
387
Elia Battiston596406d2022-02-02 12:19:00 +0100388func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
389 if speedMbps == 0 {
390 //In case it was not set in the indication
391 //and no other value was provided
392 speedMbps = defaultPortSpeedMbps
393 }
394
395 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
396 switch speedMbps {
397 case 1000000:
398 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
399 case 100000:
400 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
401 case 40000:
402 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
403 case 10000:
404 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
405 case 1000:
406 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
407 case 100:
408 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
409 case 10:
410 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
411 }
412
413 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
414
415 port := &of.OfpPort{
416 HwAddr: macAddressToUint32Array(macAddress),
417 Config: 0,
418 State: uint32(of.OfpPortState_OFPPS_LIVE),
419 Curr: capacity,
420 Advertised: capacity,
421 Peer: capacity,
422 CurrSpeed: speedMbps * 1000, //kbps
423 MaxSpeed: speedMbps * 1000, //kbps
424 }
425
426 return port
427}
428
429func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000430 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700431 if state == "up" {
432 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500433 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500434 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700435 } else {
436 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500437 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700438 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700439 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400440 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800441 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000442 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400443 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500444
khenaidoo106c61a2021-08-11 18:05:46 -0400445 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400446 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400447 DeviceId: dh.device.Id,
448 Port: portNum,
449 })
450 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000451 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400452 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400453 DeviceId: dh.device.Id,
454 PortType: portType,
455 PortNo: portNum,
456 OperStatus: operStatus})
457 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400458 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
459 "device-id": dh.device.Id,
460 "port-type": portType,
461 "port-number": portNum,
462 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500463 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400464 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500465 }
khenaidoo106c61a2021-08-11 18:05:46 -0400466
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400467 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400468 port = &voltha.Port{
469 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700470 PortNo: portNum,
471 Label: label,
472 Type: portType,
473 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100474 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700475 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000476 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700477 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400478 err = dh.createPortInCore(ctx, port)
479 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000480 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000482 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400483 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000484 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530485 return nil
486}
487
Kent Hagermane6ff1012020-07-14 15:07:53 -0400488func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400489 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530490 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400491 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
492 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530493 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800494 dh.lockDevice.Lock()
495 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530496 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530497}
498
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700499// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530500// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800501func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000502 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700503 defer func() {
504 dh.lockDevice.Lock()
505 dh.isReadIndicationRoutineActive = false
Nandita Biradar1b590f12024-09-27 10:56:28 +0530506 logger.Debugw(ctx, "isReadIndicationRoutineActive set to false", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700507 dh.lockDevice.Unlock()
508 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700509 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700510 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700511 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700512 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400513
David Bainbridgef5879ca2019-12-13 21:17:54 +0000514 // Create an exponential backoff around re-enabling indications. The
515 // maximum elapsed time for the back off is set to 0 so that we will
516 // continue to retry. The max interval defaults to 1m, but is set
517 // here for code clarity
518 indicationBackoff := backoff.NewExponentialBackOff()
519 indicationBackoff.MaxElapsedTime = 0
520 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700521
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700522 dh.lockDevice.Lock()
523 dh.isReadIndicationRoutineActive = true
Nandita Biradar1b590f12024-09-27 10:56:28 +0530524 logger.Debugw(ctx, "isReadIndicationRoutineActive set to true", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700525 dh.lockDevice.Unlock()
526
Girish Gowdra3f974912020-03-23 20:35:18 -0700527Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700528 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400529 select {
530 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000531 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700532 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400533 default:
534 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100535
536 select {
537 case <-indications.Context().Done():
538 if err != nil {
539 logger.Warnw(ctx, "error-during-enable-indications",
540 log.Fields{"err": err,
541 "device-id": dh.device.Id})
542 }
543
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400544 // Use an exponential back off to prevent getting into a tight loop
545 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100546 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
547 "device-id": dh.device.Id,
548 "duration": duration,
549 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400550 if duration == backoff.Stop {
551 // If we reach a maximum then warn and reset the backoff
552 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100553 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530554 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530555 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400556 indicationBackoff.Reset()
557 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700558
559 // On failure process a backoff timer while watching for stopIndications
560 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700561 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700562 select {
563 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000564 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700565 if !backoffTimer.Stop() {
566 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700567 }
568 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700569 case <-backoffTimer.C:
570 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700571 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700572 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
573 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400574 }
575 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100576 default:
577 if err != nil {
578 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530579 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530580 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100581 // Close the stream, and re-initialize it
582 if err = indications.CloseSend(); err != nil {
583 // Ok to ignore here, because we landed here due to a problem on the stream
584 // In all probability, the closeSend call may fail
585 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
586 log.Fields{"err": err,
587 "device-id": dh.device.Id})
588 }
589 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
590 return err
591 }
592 // once we re-initialized the indication stream, continue to read indications
593 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700594 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100595 // Reset backoff if we have a successful receive
596 indicationBackoff.Reset()
597 // When OLT is admin down, ignore all indications.
598 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
599 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
600 log.Fields{"indication": indication,
601 "device-id": dh.device.Id})
602 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700603 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100604 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530605 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700606 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700607 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700608 // Close the send stream
609 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700610
Girish Gowdra3f974912020-03-23 20:35:18 -0700611 return nil
612}
613
614func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700615 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700616 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
617 if err != nil {
618 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
619 }
620 if indications == nil {
621 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
622 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700623 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700624 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400625}
626
627// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
628func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
629 switch indication.Data.(type) {
630 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
631 return true
632
633 default:
634 return false
635 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700636}
637
David K. Bainbridge794735f2020-02-11 21:01:37 -0800638func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700639 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000640 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530641 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700642 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530643 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700644 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000645 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000646 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530647 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000648 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800649 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000650 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800651 }
652 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700653}
654
David K. Bainbridge794735f2020-02-11 21:01:37 -0800655// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530656func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700657 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658 switch indication.Data.(type) {
659 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000660 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
661 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700662 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 -0800663 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400664 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800665 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700666 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000667 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
668 defer span.Finish()
669
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700670 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100672 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400673 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800674 }
675 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000676 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000678 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
679 defer span.Finish()
680
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700681 intfOperInd := indication.GetIntfOperInd()
682 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800683 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100684 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400685 _ = 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 -0800686 }
687 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700688 } else if intfOperInd.GetType() == "pon" {
689 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
690 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800691 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100692 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400693 _ = 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 -0800694 }
695 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000696 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700697 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000698 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530699 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530700 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000702 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
703 defer span.Finish()
704
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000706 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800707 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800708 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700709 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000710 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
711 defer span.Finish()
712
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000714 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800715 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800716 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700717 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000718 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
719 defer span.Finish()
720
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700721 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000722 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 -0800723 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000724 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400725 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800726 }
727 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000729 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
730 defer span.Finish()
731
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700732 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000733 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700734 "intf-type": pktInd.IntfId,
735 "intf-id": pktInd.IntfId,
736 "gem-port-id": pktInd.GemportId,
737 "port-no": pktInd.PortNo,
738 "device-id": dh.device.Id,
739 })
740
741 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000742 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700743 "intf-type": pktInd.IntfId,
744 "intf-id": pktInd.IntfId,
745 "gem-port-id": pktInd.GemportId,
746 "port-no": pktInd.PortNo,
747 "packet": hex.EncodeToString(pktInd.Pkt),
748 "device-id": dh.device.Id,
749 })
750 }
751
David K. Bainbridge794735f2020-02-11 21:01:37 -0800752 go func() {
753 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400754 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800755 }
756 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700757 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000758 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
759 defer span.Finish()
760
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700761 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700762 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700763 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000764 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
765 defer span.Finish()
766
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700767 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000768 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000770 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
771 defer span.Finish()
772
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700773 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000774 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
775 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700776 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530777}
778
nikesh.krishnanc8473432023-06-14 12:14:54 +0530779func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
780 onuInd := &oop.OnuIndication{
781 IntfId: intfID,
782 OnuId: onuID,
783 OperState: operState,
784 AdminState: adminState,
785 }
786 indication := &oop.Indication{
787 Data: &oop.Indication_OnuInd{
788 OnuInd: onuInd,
789 },
790 }
791 return indication
792}
793
794func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
795 onuAlarmInd := &oop.OnuAlarmIndication{
796 IntfId: intfID,
797 OnuId: onuID,
798 LosStatus: losStatus,
799 }
800 alarmInd := &oop.AlarmIndication{
801 Data: &oop.AlarmIndication_OnuAlarmInd{
802 OnuAlarmInd: onuAlarmInd,
803 },
804 }
805 return alarmInd
806}
807func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
808
809 ponlosAlarmInd := &oop.LosIndication{
810 IntfId: intfID,
811 Status: losStatus,
812 }
813 alarmInd := &oop.AlarmIndication{
814 Data: &oop.AlarmIndication_LosInd{
815 LosInd: ponlosAlarmInd,
816 },
817 }
818 return alarmInd
819}
820func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
821 go func() {
822 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
823 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
824 }
825 }()
826
827 raisedTs := time.Now().Unix()
828 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
829}
830
831func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
832
833 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
834 if err != nil {
835
836 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
837
838 return err
839 }
840 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
841
842 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
843 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
844 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
845
846 onuID := onuDeviceFromCore.ProxyAddress.OnuId
847 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
848 if err != nil {
849 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
850
851 } else {
852 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
853 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
854 switch {
855 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
856 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
857 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
858
859 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
860 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") //check bal cli login notepad
861 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
862 raisedTs := time.Now().Unix()
863 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
864
865 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
866 }
867
868 }
869
870 }
871
872 return nil
873}
874
875func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
876 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
877 DeviceId: dh.device.Id,
878 PortType: voltha.Port_PON_OLT,
879 })
880 if err != nil {
881 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
882
883 return err
884
885 }
886 for _, portFromCore := range portsFromCore.Items {
887 portNum := portFromCore.GetPortNo()
888 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
889 portOperStatusFromCore := portFromCore.OperStatus
890 portAdminStateFromCore := portFromCore.AdminState
891 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
892 if err != nil {
893 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
894 } else {
895 portLosFromOlt := ponPortFromOlt.GetLos()
896 portStateFromOlt := ponPortFromOlt.GetState()
897 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
898 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
899 "portStateFromOlt": portStateFromOlt.String(),
900 "portOperStatusFromCore": portOperStatusFromCore.String(),
901 "device-id": dh.device.Id,
902 "port": portNum})
903 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
904 raisedTs := time.Now().Unix()
905 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
906
907 }
908 switch {
909 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
910 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
911 "portStateFromOlt": portStateFromOlt.String(),
912 "portOperStatusFromCore": portOperStatusFromCore.String(),
913 "device-id": dh.device.Id,
914 "port": portNum})
915 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
916 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
917 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
918 "portStateFromOlt": portStateFromOlt.String(),
919 "portOperStatusFromCore": portOperStatusFromCore.String(),
920 "device-id": dh.device.Id,
921 "port": portNum})
922 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
923 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
924 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
925 "device-id": dh.device.Id,
926 "port": portNum})
927 default:
928 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
929 "portStateFromOlt": portStateFromOlt.String(),
930 "portOperStatusFromCore": portOperStatusFromCore.String(),
931 "device-id": dh.device.Id,
932 "port": portNum})
933
934 }
935
936 }
937
938 }
939
940 return nil
941}
942
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530943// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530944func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530945 //starting the stat collector
Nandita Biradar1b590f12024-09-27 10:56:28 +0530946 // Declare deviceStateFilter to be used later
947 var deviceStateFilter *ca.DeviceStateFilter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000948 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530949 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Nandita Biradar1b590f12024-09-27 10:56:28 +0530950 if err != nil {
951 return fmt.Errorf("failed to get device from core: %w", err)
952 }
953 logger.Info(ctx, "Device state", log.Fields{
954 "device-id": device.Id,
955 "CurrOperStatus": device.OperStatus,
956 "CurrConnStatus": device.ConnectStatus,
957 })
958 // Perform cleanup if the device's operational status is REBOOTED
959 if device.OperStatus == voltha.OperStatus_RECONCILING && dh.prevOperStatus == voltha.OperStatus_REBOOTED {
960 // Log the device's operational status if it's REBOOTED
961 logger.Info(ctx, "Device is transitioning from REBOOTED to RECONCILING", log.Fields{
962 "device-id": device.Id,
963 "OperStatus": device.OperStatus,
964 })
965 dh.lockDevice.RLock()
966 // Stop the read indication only if it the routine is active
967 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
968 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
969 // on next execution of the readIndication routine.
970 if dh.isHeartbeatCheckActive {
971 dh.stopHeartbeatCheck <- true
972 }
973 if dh.isReadIndicationRoutineActive {
974 dh.stopIndications <- true
975 }
976 dh.lockDevice.RUnlock()
977 if err := dh.cleanupDeviceResources(ctx); err != nil {
978 logger.Error(ctx, "unable to clean up device resources", log.Fields{"error": err})
979 return fmt.Errorf("cleanup device resources failed: %w", err)
980 }
981 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
982 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
983 }
984 go startHeartbeatCheck(ctx, dh)
985
986 //dh.lockDevice.RUnlock()
987
988 } else if device.OperStatus == voltha.OperStatus_RECONCILING {
989 // Log the device's operational status if it's RECONCILING
990 logger.Info(ctx, "Device is being reconciled", log.Fields{
991 "device-id": device.Id,
992 "OperStatus": device.OperStatus,
993 })
994
995 // Perform reconciliation steps
996 err = dh.reconcileOnus(ctx)
997 if err != nil {
998 logger.Error(ctx, "unable to reconcile onu", log.Fields{"error": err})
999 }
1000 err = dh.reconcilePonPorts(ctx)
1001 if err != nil {
1002 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"error": err})
nikesh.krishnanc8473432023-06-14 12:14:54 +05301003 }
1004 }
Girish Gowdra618fa572021-09-01 17:19:29 -07001005 // instantiate the mcast handler routines.
1006 for i := range dh.incomingMcastFlowOrGroup {
1007 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
1008 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
1009 if !dh.mcastHandlerRoutineActive[i] {
1010 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
1011 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
1012 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
1013 // for incoming mcast flow/group to be processed serially.
1014 dh.mcastHandlerRoutineActive[i] = true
1015 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
1016 }
1017 }
Nandita Biradar1b590f12024-09-27 10:56:28 +05301018 // Create DeviceStateFilter with the desired operational and connection statuses
1019 deviceStateFilter = &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001020 DeviceId: dh.device.Id,
1021 OperStatus: voltha.OperStatus_ACTIVE,
1022 ConnStatus: voltha.ConnectStatus_REACHABLE,
Nandita Biradar1b590f12024-09-27 10:56:28 +05301023 }
1024 // Log DeviceStateFilter for debugging purposes
1025 logger.Info(ctx, "DeviceStateFilter", log.Fields{
1026 "DeviceId": deviceStateFilter.DeviceId,
1027 "OperStatus": deviceStateFilter.OperStatus,
1028 "ConnStatus": deviceStateFilter.ConnStatus,
1029 })
1030 // Synchronous call to update device state - this method is run in its own go routine
1031 if err := dh.updateDeviceStateInCore(ctx, deviceStateFilter); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001032 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001033 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001034
1035 //Clear olt communication failure event
1036 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1037 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001038 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00001039 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
1040
Girish Gowdru0c588b22019-04-23 23:24:56 -04001041 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301042}
1043
1044// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +05301045func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001046 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -04001047
khenaidoo106c61a2021-08-11 18:05:46 -04001048 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -04001049 if err != nil || device == nil {
1050 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +00001051 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001052 }
1053
1054 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001055
1056 //Update the device oper state and connection status
1057 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001058 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001059 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001060 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001061
khenaidoodc2116e2021-10-19 17:33:19 -04001062 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001063 DeviceId: cloned.Id,
1064 OperStatus: cloned.OperStatus,
1065 ConnStatus: cloned.ConnectStatus,
1066 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001067 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001068 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001069
1070 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001071 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001072 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001073 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001074 }
1075 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001076 // Update onu state as down in onu adapter
1077 onuInd := oop.OnuIndication{}
1078 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001079
1080 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1081 if err != nil {
1082 return err
1083 }
1084 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001085 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001086 DeviceId: onuDevice.Id,
1087 OnuIndication: &onuInd,
1088 })
1089 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001091 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001092 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 "onu-indicator": onuInd,
1094 "device-type": onuDevice.Type,
1095 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -07001096 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001097 } else {
1098 logger.Debugw(ctx, "sending inter adapter down ind to onu success", log.Fields{"olt-device-id": device.Id, "onu-device-id": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001099 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001100 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001101 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001102 /* Discovered ONUs entries need to be cleared , since after OLT
1103 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301104 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001105 dh.lockDevice.Unlock()
1106
Neha Sharma96b7bf22020-06-15 10:37:32 +00001107 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001108 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301109}
1110
1111// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301112func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001113 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001114
1115 // if the connection is already available, close the previous connection (olt reboot case)
1116 if dh.clientCon != nil {
1117 if err = dh.clientCon.Close(); err != nil {
1118 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1119 } else {
1120 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1121 }
1122 }
1123
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301124 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +00001125 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001126 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1127 grpc.WithInsecure(),
1128 grpc.WithBlock(),
1129 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001130 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001131 )),
1132 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001133 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001134 )))
1135
1136 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301137 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301138 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001139 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001140 }
Akash Sonif49299a2024-04-25 12:06:37 +05301141 //Setting oper and connection state to RECONCILING and conn state to reachable
1142 cgClient, err := dh.coreClient.GetCoreServiceClient()
1143 if err != nil {
1144 return err
1145 }
1146
1147 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1148 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1149 defer cancel()
1150 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1151 DeviceId: dh.device.Id,
1152 OperStatus: voltha.OperStatus_RECONCILING,
1153 ConnStatus: voltha.ConnectStatus_REACHABLE,
1154 }); err != nil {
1155 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1156 }
1157 // The OperState and connection state of the device is set to RECONCILING and REACHABLE in the previous section. This also needs to be set on the
1158 // locally cached copy of the device struct.
1159 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1160 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1161 }
1162
Girish Gowdru0c588b22019-04-23 23:24:56 -04001163 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301164}
1165
1166// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301167func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001168 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301169 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001170 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301171}
1172
1173// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301174func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301175 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001176 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001177
1178 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001179 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301180 if err != nil || device == nil {
1181 /*TODO: needs to handle error scenarios */
1182 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1183 }
1184 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001185 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001186
1187 cloned := proto.Clone(device).(*voltha.Device)
1188 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1189 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1190 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001191
khenaidoodc2116e2021-10-19 17:33:19 -04001192 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001193 DeviceId: cloned.Id,
1194 OperStatus: cloned.OperStatus,
1195 ConnStatus: cloned.ConnectStatus,
1196 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301197 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001198 }
1199
Chaitrashree G S44124192019-08-07 20:21:36 -04001200 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
npujarec5762e2020-01-01 14:08:48 +05301201 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001202 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301203 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001204 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001205 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1206 // all the modules initialized and ready to handle incoming ONUs.
1207
Thomas Lee S985938d2020-05-04 11:40:41 +05301208 err = dh.initializeDeviceHandlerModules(ctx)
1209 if err != nil {
1210 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001211 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001212
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001213 go startHeartbeatCheck(ctx, dh)
1214
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001215 return nil
1216 }
1217
khenaidoo106c61a2021-08-11 18:05:46 -04001218 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001219 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -04001220 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001221 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001222 }
khenaidoo106c61a2021-08-11 18:05:46 -04001223 dh.populateActivePorts(ctx, ports.Items)
1224 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001225 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001226 }
1227
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001228 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301229 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 -04001230 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301231
Neha Sharma96b7bf22020-06-15 10:37:32 +00001232 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001233
1234 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001235 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001236 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001237
1238 go startHeartbeatCheck(ctx, dh)
1239
cuilin20187b2a8c32019-03-26 19:52:28 -07001240 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301241}
1242
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001243func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001244 var err error
1245 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001246
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001247 if dh.flowMgr != nil {
1248 dh.StopAllFlowRoutines(ctx)
1249 }
1250
1251 dh.CloseKVClient(ctx)
1252
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001253 if err != nil {
1254 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1255 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001256 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1257 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +00001258 // +1 is for NNI
1259 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1260 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001261 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001262 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1263 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1264 // There is only one NNI manager since multiple NNI is not supported for now
1265 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001266 // Instantiate resource manager
1267 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 -07001268 return olterrors.ErrResourceManagerInstantiating
1269 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001270 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001271 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1272 // the KV store to manage mcast group data. Provide the first instance (0th index)
1273 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1274 return olterrors.ErrGroupManagerInstantiating
1275 }
yasin saplid0566272021-12-21 09:10:30 +00001276 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001277 // Instantiate flow manager
1278 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001279 //Continue to check the rest of the ports
1280 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1281 } else {
1282 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001283 }
1284 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001285 /* TODO: Instantiate Alarm , stats , BW managers */
1286 /* Instantiating Event Manager to handle Alarms and KPIs */
1287 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1288
1289 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001290 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001291
1292 return nil
1293
1294}
1295
Neha Sharma96b7bf22020-06-15 10:37:32 +00001296func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001297 var err error
1298 var deviceInfo *oop.DeviceInfo
1299
Neha Sharma8f4e4322020-08-06 10:51:53 +00001300 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001301
1302 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001303 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001304 }
1305 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001306 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001307 }
1308
Neha Sharma96b7bf22020-06-15 10:37:32 +00001309 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001310 dh.device.Root = true
1311 dh.device.Vendor = deviceInfo.Vendor
1312 dh.device.Model = deviceInfo.Model
1313 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1314 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1315 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1316
1317 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001318 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001319 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001320 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001321 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001322 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001323 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001324 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001325 dh.device.MacAddress = genmac
1326 } else {
1327 dh.device.MacAddress = deviceInfo.DeviceId
1328 }
1329
1330 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001331 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001332 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001333 }
1334
1335 return deviceInfo, nil
1336}
1337
Neha Sharma96b7bf22020-06-15 10:37:32 +00001338func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001339 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001340
1341 defer func() {
1342 dh.lockDevice.Lock()
1343 dh.isCollectorActive = false
1344 dh.lockDevice.Unlock()
1345 }()
1346
1347 dh.lockDevice.Lock()
1348 dh.isCollectorActive = true
1349 dh.lockDevice.Unlock()
1350
Naga Manjunath7615e552019-10-11 22:35:47 +05301351 for {
1352 select {
1353 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001354 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301355 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001356 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001357
khenaidoo106c61a2021-08-11 18:05:46 -04001358 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001359 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001360 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001361 continue
1362 }
khenaidoo106c61a2021-08-11 18:05:46 -04001363 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301364 // NNI Stats
1365 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001366 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301367 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001368 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001369 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001370 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301371 }
1372 // PON Stats
1373 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001374 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301375 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1376 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001377 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001378 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301379 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001380 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001381
yasin sapli9e4c5092022-02-01 13:52:33 +00001382 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001383 if len(onuGemInfoLst) > 0 {
1384 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001385 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001386 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301387 }
1388 }
1389 }
1390}
1391
Mahir Gunyela2e68702022-12-07 00:00:42 -08001392// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301393func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001394 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001395 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301396 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301397
1398 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001399 cgClient, err := dh.coreClient.GetCoreServiceClient()
1400 if err != nil {
1401 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1402 return
1403 }
1404
1405 // Now, set the initial PM configuration for that device
1406 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001407 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301408 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301409}
1410
Mahir Gunyela2e68702022-12-07 00:00:42 -08001411// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001412func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1413 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001414 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301415 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001416 HwDesc: "open_pon",
1417 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001418 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001419 },
1420 SwitchFeatures: &of.OfpSwitchFeatures{
1421 NBuffers: 256,
1422 NTables: 2,
1423 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1424 of.OfpCapabilities_OFPC_TABLE_STATS |
1425 of.OfpCapabilities_OFPC_PORT_STATS |
1426 of.OfpCapabilities_OFPC_GROUP_STATS),
1427 },
1428 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301429}
1430
khenaidoo106c61a2021-08-11 18:05:46 -04001431// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001432func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001433 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001434 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001435 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001436 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001437 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1438 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()
1439 }
khenaidoo106c61a2021-08-11 18:05:46 -04001440 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Mahir Gunyela2e68702022-12-07 00:00:42 -08001441
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001442}
1443
Neha Sharma96b7bf22020-06-15 10:37:32 +00001444func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001445 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 -07001446 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001447 var deviceID string
1448 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001449 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001450
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001451 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001452 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001453 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 -07001454 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1455 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001456
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001457 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301458
1459 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1460
Neha Sharma96b7bf22020-06-15 10:37:32 +00001461 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 -07001462 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001463
khenaidoodc2116e2021-10-19 17:33:19 -04001464 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001465 ParentId: dh.device.Id,
1466 OnuId: omciInd.OnuId,
1467 ParentPortNo: ponPort,
1468 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001469 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301470 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001471 "intf-id": omciInd.IntfId,
1472 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001473 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001474 deviceType = onuDevice.Type
1475 deviceID = onuDevice.Id
1476 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001477 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001478 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001479 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001480 } else {
1481 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001482 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 +05301483 deviceType = onuInCache.(*OnuDevice).deviceType
1484 deviceID = onuInCache.(*OnuDevice).deviceID
1485 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001486 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001487 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001488
khenaidoodc2116e2021-10-19 17:33:19 -04001489 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001490 ParentDeviceId: proxyDeviceID,
1491 ChildDeviceId: deviceID,
1492 Message: omciInd.Pkt,
1493 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301494 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001495 "source": dh.openOLT.config.AdapterEndpoint,
1496 "device-type": deviceType,
1497 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001498 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001499 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001500 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001501 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301502}
1503
khenaidoo106c61a2021-08-11 18:05:46 -04001504// //ProcessInterAdapterMessage sends the proxied messages to the target device
1505// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1506// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001507// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001508// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001509// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001510// return dh.handleInterAdapterOmciMsg(ctx, msg)
1511// }
1512// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1513// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001514
kesavandb9f54fd2021-11-25 20:08:04 +05301515// ProxyOmciRequests sends the proxied OMCI message to the target device
1516func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301517 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1518 return status.Error(codes.Unavailable, "OLT unreachable")
1519 }
kesavandb9f54fd2021-11-25 20:08:04 +05301520 if omciMsgs.GetProxyAddress() == nil {
1521 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1522 if err != nil {
1523 return olterrors.NewErrNotFound("onu", log.Fields{
1524 "parent-device-id": dh.device.Id,
1525 "child-device-id": omciMsgs.ChildDeviceId}, err)
1526 }
1527 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1528 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1529 return olterrors.NewErrCommunication("send-failed", log.Fields{
1530 "parent-device-id": dh.device.Id,
1531 "child-device-id": omciMsgs.ChildDeviceId}, err)
1532 }
1533 } else {
1534 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1535 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1536 return olterrors.NewErrCommunication("send-failed", log.Fields{
1537 "parent-device-id": dh.device.Id,
1538 "child-device-id": omciMsgs.ChildDeviceId}, err)
1539 }
1540 }
1541 return nil
1542}
1543
1544func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1545 var intfID uint32
1546 var onuID uint32
1547 var connectStatus common.ConnectStatus_Types
1548 if onuDevice != nil {
1549 intfID = onuDevice.ProxyAddress.GetChannelId()
1550 onuID = onuDevice.ProxyAddress.GetOnuId()
1551 connectStatus = onuDevice.ConnectStatus
1552 } else {
1553 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1554 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1555 connectStatus = omciMsgs.GetConnectStatus()
1556 }
1557 if connectStatus != voltha.ConnectStatus_REACHABLE {
1558 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1559
1560 return olterrors.NewErrCommunication("unreachable", log.Fields{
1561 "intf-id": intfID,
1562 "onu-id": onuID}, nil)
1563 }
1564
1565 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1566 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1567
1568 onuSecOmciMsgList := omciMsgs.GetMessages()
1569
1570 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1571
1572 var omciMessage *oop.OmciMsg
1573 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1574 hex.Encode(hexPkt, onuSecOmciMsg)
1575 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1576
1577 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1578 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1579 //https://jira.opencord.org/browse/VOL-4604
1580 transid := extractOmciTransactionID(onuSecOmciMsg)
1581 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1582 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1583
1584 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1585 if err != nil {
1586 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1587 "intf-id": intfID,
1588 "onu-id": onuID,
1589 "message": omciMessage}, err)
1590 }
1591 }
1592 return nil
1593}
1594
khenaidoo106c61a2021-08-11 18:05:46 -04001595// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001596func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001597 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 -07001598
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301599 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1600 return status.Error(codes.Unavailable, "OLT unreachable")
1601 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001602 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001603 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001604 if err != nil {
1605 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001606 "parent-device-id": dh.device.Id,
1607 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001608 }
khenaidoo106c61a2021-08-11 18:05:46 -04001609 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1610 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001611 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001612 "parent-device-id": dh.device.Id,
1613 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001614 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001615 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001616 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1617 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001618 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001619 "parent-device-id": dh.device.Id,
1620 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001621 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001622 }
1623 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301624}
1625
khenaidoodc2116e2021-10-19 17:33:19 -04001626func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001627 var intfID uint32
1628 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001629 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001630 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001631 intfID = onuDevice.ProxyAddress.GetChannelId()
1632 onuID = onuDevice.ProxyAddress.GetOnuId()
1633 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001634 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001635 intfID = omciMsg.GetProxyAddress().GetChannelId()
1636 onuID = omciMsg.GetProxyAddress().GetOnuId()
1637 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001638 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001639 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001640 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 -08001641
Thomas Lee S94109f12020-03-03 16:39:29 +05301642 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001643 "intf-id": intfID,
1644 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001645 }
1646
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001647 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1648 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301649 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001650 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001651 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1652 hex.Encode(hexPkt, omciMsg.Message)
1653 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1654
1655 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1656 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1657 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001658 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001659 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001660
Neha Sharma8f4e4322020-08-06 10:51:53 +00001661 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001662 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301663 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001664 "intf-id": intfID,
1665 "onu-id": onuID,
1666 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001667 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001668 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001669}
1670
David K. Bainbridge794735f2020-02-11 21:01:37 -08001671func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301672 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 +00001673 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001674 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001675 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001676 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301677 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301678 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001679 st, _ := status.FromError(err)
1680 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001681 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1682
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001683 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301684 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001685 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001686 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001687 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001688 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001689 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001690}
1691
Mahir Gunyela2e68702022-12-07 00:00:42 -08001692// getChildDevice function can be used in general to get child device, if not found in cache the function will
1693// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301694func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1695 var InCacheOnuDev *OnuDevice
1696 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1697 if onuInCache.(*OnuDevice).serialNumber == sn {
1698 InCacheOnuDev = onuInCache.(*OnuDevice)
1699 return false
1700 }
1701 return true
1702 })
1703 //Got the onu device from cache return
1704 if InCacheOnuDev != nil {
1705 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1706 return InCacheOnuDev
1707 }
1708 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1709 ParentId: dh.device.Id,
1710 SerialNumber: sn,
1711 ParentPortNo: parentPortNo,
1712 })
1713 //No device found in core return nil
1714 if onuDevice == nil {
1715 return nil
1716 }
1717 onuID := onuDevice.ProxyAddress.OnuId
1718 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1719 onuKey := dh.formOnuKey(intfID, onuID)
1720
1721 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1722 dh.onus.Store(onuKey, onuDev)
1723 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1724 return onuDev
1725}
1726
1727func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001728 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001729 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301730 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001731
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301732 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1733 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1734 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1735 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1736 if onuDev != nil {
1737 var onuGemInfo *rsrcMgr.OnuGemInfo
1738 var err error
1739 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1740 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1741 return false, err
1742 }
1743 if onuGemInfo != nil {
1744 for _, uni := range onuGemInfo.UniPorts {
1745 uniID := plt.UniIDFromPortNum(uni)
1746 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1747 if len(tpIDs) != 0 {
1748 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1749 tpInstExists = true
1750 break
1751 }
1752 }
1753 }
1754 }
1755 return tpInstExists, nil
1756 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301757
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301758 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1759 ParentId: dh.device.Id,
1760 SerialNumber: sn,
1761 ParentPortNo: parentPortNo,
1762 })
1763 if onuDevice != nil {
1764 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1765 return true, nil
1766 }
1767 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1768
1769 return false, nil
1770
1771}
1772
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001773// processDiscONULOSClear clears the LOS Alarm if it's needed
1774func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301775 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001776 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301777
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001778 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1779 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1780 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1781 OnuLosRaise event sent for it */
1782 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1783 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1784 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1785 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1786 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1787 "currentIntfId": onuDiscInd.GetIntfId()})
1788 // TODO:: Should we need to ignore raising OnuLosClear event
1789 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301790 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001791 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1792 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1793 alarmInd.LosStatus = statusCheckOff
1794 go func() {
1795 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1796 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1797 }
1798 }()
1799 // stop iterating
1800 return false
1801 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301802 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001803 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301804}
1805
1806func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301807 var error error
1808
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301809 channelID := onuDiscInd.GetIntfId()
1810 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1811
1812 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301813 defer func() {
1814 if error != nil {
1815 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1816 } else {
1817 // once the function completes set the value to false so that
1818 // we know the processing has inProcess.
1819 // Note that this is done after checking if we are already processing
1820 // to avoid changing the value from a different thread
1821 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1822 dh.discOnus.Store(sn, false)
1823 }
1824 }()
1825
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301826 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1827
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301828 tpInstExists, error := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1829 if error != nil {
1830 return error
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301831 }
1832 if tpInstExists {
1833 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001834 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001835 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001836 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001837 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1838
1839 // if the ONU existed, handle the LOS Alarm
1840 if existing {
1841
1842 if inProcess.(bool) {
1843 // if we're currently processing the ONU on a different thread, do nothing
1844 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1845 return nil
1846 }
1847 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1848 // then continue processing it
1849 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1850
1851 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001852 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301853 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001854 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001855
1856 // check the ONU is already know to the OLT
1857 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301858 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001859 ParentId: dh.device.Id,
1860 SerialNumber: sn,
1861 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001862
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301863 if error != nil {
1864 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1865 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001866 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 -08001867 switch e.Code() {
1868 case codes.Internal:
1869 // this probably means NOT FOUND, so just create a new device
1870 onuDevice = nil
1871 case codes.DeadlineExceeded:
1872 // if the call times out, cleanup and exit
1873 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301874 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1875 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001876 }
1877 }
1878 }
1879
1880 if onuDevice == nil {
1881 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001882 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001883 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001884 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301885 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001886
Neha Sharma96b7bf22020-06-15 10:37:32 +00001887 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001888
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301889 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001890 // if we can't create an ID in resource manager,
1891 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001892 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301893
1894 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001895 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301896 "serial-number": sn}, error)
1897 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001898 }
1899
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301900 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001901 ParentId: dh.device.Id,
1902 ParentPortNo: parentPortNo,
1903 ChannelId: channelID,
1904 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1905 SerialNumber: sn,
1906 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301907 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001908 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001909 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 +05301910
1911 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001912 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301913 "serial-number": sn}, error)
1914 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001915 }
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301916 if error := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); error != nil {
1917 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
1918 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
1919 "onu-id": onuID,
1920 "device-id": dh.device.Id,
1921 "serial-number": sn}, error)
1922 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04001923 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001924 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301925 log.Fields{"onuDevice": onuDevice,
1926 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001927 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301928 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001929 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001930
khenaidoo106c61a2021-08-11 18:05:46 -04001931 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1932 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301933 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04001934 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301935 if error != nil {
1936
1937 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
1938 return error
khenaidoo106c61a2021-08-11 18:05:46 -04001939 }
1940
Matteo Scandolo945e4012019-12-12 14:16:11 -08001941 // we can now use the existing ONU Id
1942 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001943 //Insert the ONU into cache to use in OnuIndication.
1944 //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 +00001945 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001946 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301947 "intfId": onuDiscInd.GetIntfId(),
1948 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001949 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001950
khenaidoo106c61a2021-08-11 18:05:46 -04001951 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301952 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001953 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301954 log.Fields{"onu": onuDev,
1955 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001956
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301957 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001958 DeviceId: onuDevice.Id,
1959 ParentDeviceId: dh.device.Id,
1960 OperStatus: common.OperStatus_DISCOVERED,
1961 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301962 }); error != nil {
1963
1964 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001965 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301966 "serial-number": sn}, error)
1967 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07001968 }
khenaidoo106c61a2021-08-11 18:05:46 -04001969
Neha Sharma96b7bf22020-06-15 10:37:32 +00001970 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301971 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
1972
1973 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001974 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301975 "serial-number": sn}, error)
1976 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08001977 }
1978 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001979}
1980
Mahir Gunyelb0046752021-02-26 13:51:05 -08001981func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001982
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001983 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001984 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001985 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001986 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001987 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301988 log.Fields{"onuId": onuInd.OnuId,
1989 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301990 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001991 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001992 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301993
David K. Bainbridge794735f2020-02-11 21:01:37 -08001994 errFields := log.Fields{"device-id": dh.device.Id}
1995
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301996 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1997
Mahir Gunyele77977b2019-06-27 05:36:22 -07001998 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1999 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08002000 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04002001 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07002002 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07002003 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
2004 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002005 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07002006 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002007 errFields["onu-id"] = onuInd.OnuId
2008 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07002009 }
khenaidoodc2116e2021-10-19 17:33:19 -04002010 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002011 ParentId: dh.device.Id,
2012 SerialNumber: serialNumber,
2013 OnuId: onuInd.OnuId,
2014 ParentPortNo: ponPort,
2015 })
cuilin20187b2a8c32019-03-26 19:52:28 -07002016 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07002017
David K. Bainbridge794735f2020-02-11 21:01:37 -08002018 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002019 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07002020 }
2021
David K. Bainbridge794735f2020-02-11 21:01:37 -08002022 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002023 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002024 "previousIntfId": onuDevice.ParentPortNo,
2025 "currentIntfId": ponPort})
2026 }
2027
2028 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002029 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302030 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
2031 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05302032 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002033 }
2034 if !foundInCache {
2035 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
2036
khenaidoo106c61a2021-08-11 18:05:46 -04002037 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 -08002038
2039 }
kesavand7cf3a052020-08-28 12:49:18 +05302040 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002041 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002042 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05302043 }
2044 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002045 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002046 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002047 }
2048 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07002049}
2050
Neha Sharma96b7bf22020-06-15 10:37:32 +00002051func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002052 logger.Debugw(ctx, "onu-indication-for-state", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdra748de5c2020-07-01 10:27:52 -07002053 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
2054 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2055 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2056 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002057 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002058 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2059 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002060 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002061 onuInd.OperState = "down"
2062 }
2063 }
2064
David K. Bainbridge794735f2020-02-11 21:01:37 -08002065 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002066 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002067 logger.Debugw(ctx, "sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
khenaidoo106c61a2021-08-11 18:05:46 -04002068
khenaidoodc2116e2021-10-19 17:33:19 -04002069 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002070 DeviceId: onuDevice.Id,
2071 OnuIndication: onuInd,
2072 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002073 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302074 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002075 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002076 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002077 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002078 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002079 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002080 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002081 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002082 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002083 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002084}
2085
cuilin20187b2a8c32019-03-26 19:52:28 -07002086func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2087 if serialNum != nil {
2088 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002089 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002090 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002091}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002092func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2093 decodedStr, err := hex.DecodeString(serialNum[4:])
2094 if err != nil {
2095 return nil, err
2096 }
2097 return &oop.SerialNumber{
2098 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002099 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002100 }, nil
2101}
cuilin20187b2a8c32019-03-26 19:52:28 -07002102
2103func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002104 if len(vendorSpecific) > 3 {
2105 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2106 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2107 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2108 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2109 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2110 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2111 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2112 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2113 return tmp
2114 }
2115 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002116}
2117
Mahir Gunyela2e68702022-12-07 00:00:42 -08002118// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002119func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302120 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002121}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002122
Mahir Gunyela2e68702022-12-07 00:00:42 -08002123// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002124func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2125 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302126 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002127 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302128 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002129
khenaidoodc2116e2021-10-19 17:33:19 -04002130 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002131 ParentId: dh.device.Id,
2132 OnuId: onuID,
2133 ParentPortNo: parentPort,
2134 })
2135
Girish Gowdru0c588b22019-04-23 23:24:56 -04002136 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002137 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002138 "intf-id": parentPort,
2139 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002140 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002141 logger.Debugw(ctx, "successfully-received-child-device-from-core", log.Fields{"child-device-id": onuDevice.Id, "child-device-sn": onuDevice.SerialNumber})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002142 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302143}
2144
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002145// SendPacketInToCore sends packet-in to core
2146// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2147// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002148func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002149 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002150 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002151 "port": logicalPort,
2152 "packet": hex.EncodeToString(packetPayload),
2153 "device-id": dh.device.Id,
2154 })
2155 }
khenaidoo106c61a2021-08-11 18:05:46 -04002156
khenaidoodc2116e2021-10-19 17:33:19 -04002157 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002158 DeviceId: dh.device.Id,
2159 Port: logicalPort,
2160 Packet: packetPayload,
2161 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302162 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002163 "source": "adapter",
2164 "destination": "core",
2165 "device-id": dh.device.Id,
2166 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002167 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002168 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002169 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002170 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002171 "packet": hex.EncodeToString(packetPayload),
2172 "device-id": dh.device.Id,
2173 })
2174 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002175 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002176}
2177
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002178// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002179func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002180 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002181
2182 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2183 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002185 }
2186
Kent Hagermane6ff1012020-07-14 15:07:53 -04002187 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002188 metrics := dh.metrics.GetSubscriberMetrics()
2189 for _, m := range pmConfigs.Metrics {
2190 metrics[m.Name].Enabled = m.Enabled
2191
2192 }
2193 }
2194}
2195
khenaidoodc2116e2021-10-19 17:33:19 -04002196func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002197 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002198 var errorsList []error
2199
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002200 if dh.getDeviceDeletionInProgressFlag() {
2201 // The device itself is going to be reset as part of deletion. So nothing to be done.
2202 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2203 return nil
2204 }
2205
Girish Gowdru0c588b22019-04-23 23:24:56 -04002206 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002207 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00002208 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002209
Neha Sharma96b7bf22020-06-15 10:37:32 +00002210 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302211 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002212 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302213 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002214 if flow_utils.HasGroup(flow) {
2215 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2216 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002217 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2218 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2219 } else {
2220 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2221 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002222 }
Girish Gowdracefae192020-03-19 18:14:10 -07002223 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002224 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
2225 //The flow we want to remove is not there, there is no need to throw an error
2226 logger.Warnw(ctx, "flow-to-remove-not-found",
2227 log.Fields{
2228 "ponIf": intfID,
2229 "flowToRemove": flow,
2230 "error": err,
2231 })
2232 } else {
2233 errorsList = append(errorsList, err)
2234 }
Girish Gowdracefae192020-03-19 18:14:10 -07002235 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002236 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302237
2238 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00002239 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002240 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302241 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002242 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302243 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002244 if flow_utils.HasGroup(flow) {
2245 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2246 } else {
yasin saplid0566272021-12-21 09:10:30 +00002247 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002248 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2249 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2250 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2251 } else {
yasin saplid0566272021-12-21 09:10:30 +00002252 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002253 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002254 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002255 if err != nil {
2256 errorsList = append(errorsList, err)
2257 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302258 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002259 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002260
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002261 return errorsList
2262}
2263
2264func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2265 var err error
2266 var errorsList []error
2267
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002268 if dh.getDeviceDeletionInProgressFlag() {
2269 // The device itself is going to be reset as part of deletion. So nothing to be done.
2270 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2271 return nil
2272 }
2273
Girish Gowdracefae192020-03-19 18:14:10 -07002274 // 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 +00002275 if groups != nil {
2276 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002277 // err = dh.groupMgr.AddGroup(ctx, group)
2278 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002279 if err != nil {
2280 errorsList = append(errorsList, err)
2281 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002282 }
2283 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002284 // err = dh.groupMgr.ModifyGroup(ctx, group)
2285 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002286 if err != nil {
2287 errorsList = append(errorsList, err)
2288 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002289 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002290 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002291 // err = dh.groupMgr.DeleteGroup(ctx, group)
2292 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002293 if err != nil {
2294 errorsList = append(errorsList, err)
2295 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002296 }
2297 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002298
2299 return errorsList
2300}
2301
Mahir Gunyela2e68702022-12-07 00:00:42 -08002302// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002303func (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 -07002304
2305 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002306
2307 if dh.getDeviceDeletionInProgressFlag() {
2308 // The device itself is going to be reset as part of deletion. So nothing to be done.
2309 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2310 return nil
2311 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302312 if dh.transitionMap.currentDeviceState != deviceStateUp {
2313 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2314 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2315 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002316 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2317 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2318 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002319 if len(errorsList) > 0 {
2320 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2321 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002322 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002323 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302324}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002325
Mahir Gunyela2e68702022-12-07 00:00:42 -08002326// DisableDevice disables the given device
2327// It marks the following for the given device:
2328// Device-Handler Admin-State : down
2329// Device Port-State: UNKNOWN
2330// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002331func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002332 /* On device disable ,admin state update has to be done prior sending request to agent since
2333 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002334 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002335 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002336 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002337 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002338 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002339 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002340 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002341 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002342 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002343 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302344
2345 dh.discOnus = sync.Map{}
2346 dh.onus = sync.Map{}
2347
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002348 dh.lockDevice.RLock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302349 //stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002350 if dh.isCollectorActive {
2351 dh.stopCollector <- true
2352 }
2353 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302354
Neha Sharma96b7bf22020-06-15 10:37:32 +00002355 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002356 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05302357 //Update device Admin state
2358 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002359
kdarapu1afeceb2020-02-12 01:38:09 -05002360 // 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 -04002361 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002362 DeviceId: cloned.Id,
2363 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2364 OperStatus: voltha.OperStatus_UNKNOWN,
2365 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002366 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002367 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002368 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002369 return nil
2370}
2371
Neha Sharma96b7bf22020-06-15 10:37:32 +00002372func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002373 // Update onu state as unreachable in onu adapter
2374 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302375 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002376
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002377 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002378 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002379 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002380 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 -04002381 }
2382 if onuDevices != nil {
2383 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002384 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002385 DeviceId: onuDevice.Id,
2386 OnuIndication: &onuInd,
2387 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002388 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002390 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002391 }
2392
2393 }
2394 }
2395
2396}
2397
Mahir Gunyela2e68702022-12-07 00:00:42 -08002398// ReenableDevice re-enables the olt device after disable
2399// It marks the following for the given device:
2400// Device-Handler Admin-State : up
2401// Device Port-State: ACTIVE
2402// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002403func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302404 if dh.Client != nil {
2405 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2406 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2407 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2408 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302409 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302410 } else {
2411 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2412
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302413 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302414
Neha Sharma96b7bf22020-06-15 10:37:32 +00002415 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002416
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002417 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002418 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002419 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002420 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002421 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2422 } else {
2423 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2424 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2425 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002426 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002427 if retError == nil {
2428 //Update the device oper status as ACTIVE
2429 device.OperStatus = voltha.OperStatus_ACTIVE
2430 } else {
2431 //Update the device oper status as FAILED
2432 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002433 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002434 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002435
khenaidoodc2116e2021-10-19 17:33:19 -04002436 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002437 DeviceId: device.Id,
2438 OperStatus: device.OperStatus,
2439 ConnStatus: device.ConnectStatus,
2440 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302441 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002442 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002443 "connect-status": device.ConnectStatus,
2444 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002445 }
kesavand39e0aa32020-01-28 20:58:50 -05002446
Neha Sharma96b7bf22020-06-15 10:37:32 +00002447 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002448
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002449 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002450}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002451
npujarec5762e2020-01-01 14:08:48 +05302452func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002453 var uniID uint32
2454 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002455 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302456 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002457 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002458 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002459 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002460 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2461 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2462 } else {
2463 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2464 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002465 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002466 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002467 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002468 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002469 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002470 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002471 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002472 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002473 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002474 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002475 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002476 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002477 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002478 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002479 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002480 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302481 }
yasin saplibddc2d72022-02-08 13:10:17 +00002482 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2483 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002484 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002485 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302486 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002487 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002488 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002489 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 -03002490 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002491 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002492 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002493 if len(errs) > 0 {
2494 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2495 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2496 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002497 return nil
2498}
2499
Devmalya Paul495b94a2019-08-27 19:42:00 -04002500// 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 +05302501func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002502 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002503 /* Clear the KV store data associated with the all the UNI ports
2504 This clears up flow data and also resource map data for various
2505 other pon resources like alloc_id and gemport_id
2506 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002507
2508 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002509
2510 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002511
Gustavo Silva41af9122022-10-11 11:05:13 -03002512 err := dh.cleanupDeviceResources(ctx)
2513 if err != nil {
2514 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2515 } else {
2516 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2517 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002518
Himani Chawla49a5d562020-11-25 11:53:44 +05302519 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002520 // Stop the Stats collector
2521 if dh.isCollectorActive {
2522 dh.stopCollector <- true
2523 }
2524 // stop the heartbeat check routine
2525 if dh.isHeartbeatCheckActive {
2526 dh.stopHeartbeatCheck <- true
2527 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302528 // Stop the read indication only if it the routine is active
2529 if dh.isReadIndicationRoutineActive {
2530 dh.stopIndications <- true
2531 }
2532 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002533 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002534 //Reset the state
2535 if dh.Client != nil {
2536 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002537 go func() {
2538 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
2539 if err = dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err != nil {
2540 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
2541 }
2542 }()
2543 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002544 }
2545 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002546 // There is no need to update the core about operation status and connection status of the OLT.
2547 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2548 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2549 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002550
khenaidoo7eb2d672021-10-22 19:08:50 -04002551 // Stop the adapter grpc clients for that parent device
2552 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002553 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002554}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002555
2556// StopAllFlowRoutines stops all flow routines
2557func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2558 var wg sync.WaitGroup
2559 wg.Add(1) // for the mcast routine below to finish
2560 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2561 for _, flMgr := range dh.flowMgr {
2562 if flMgr != nil {
2563 wg.Add(1) // for the flow handler routine below to finish
2564 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2565 }
2566 }
2567 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2568 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2569 } else {
2570 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2571 }
2572}
2573
Gustavo Silva41af9122022-10-11 11:05:13 -03002574func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2575 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002576 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302577 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002578 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002579 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002580 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002581 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002582 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2583 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302584 }
2585 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002586 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2587 errs = append(errs, err)
2588 }
2589 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2590 errs = append(errs, err)
2591 }
2592 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2593 errs = append(errs, err)
2594 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002595 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002596 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002597 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002598 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002599 }
2600 // Clean up NNI manager's data
2601 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2602 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002603 }
A R Karthick1f85b802019-10-11 05:06:05 +00002604
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002605 dh.CloseKVClient(ctx)
2606
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002607 // Take one final sweep at cleaning up KV store for the OLT device
2608 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002609 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2610 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002611 }
2612
Devmalya Paul495b94a2019-08-27 19:42:00 -04002613 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302614 dh.onus.Range(func(key interface{}, value interface{}) bool {
2615 dh.onus.Delete(key)
2616 return true
2617 })
2618
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002619 /*Delete discovered ONU map for the device*/
2620 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2621 dh.discOnus.Delete(key)
2622 return true
2623 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002624 if len(errs) > 0 {
2625 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2626 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2627 }
2628 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002629}
2630
Mahir Gunyela2e68702022-12-07 00:00:42 -08002631// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002632func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302633 if dh.Client != nil {
2634 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2635 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2636 }
2637 } else {
2638 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2639
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002640 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302641
Neha Sharma96b7bf22020-06-15 10:37:32 +00002642 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002643 return nil
2644}
2645
David K. Bainbridge794735f2020-02-11 21:01:37 -08002646func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002647 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002648 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002649 "packet-indication": *packetIn,
2650 "device-id": dh.device.Id,
2651 "packet": hex.EncodeToString(packetIn.Pkt),
2652 })
2653 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002654 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2655 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2656 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002657 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002658 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002659 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002660 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002661 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002662 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002663 "logical-port-num": logicalPortNum,
2664 "device-id": dh.device.Id,
2665 "packet": hex.EncodeToString(packetIn.Pkt),
2666 })
2667 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002668
khenaidoodc2116e2021-10-19 17:33:19 -04002669 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002670 DeviceId: dh.device.Id,
2671 Port: logicalPortNum,
2672 Packet: packetIn.Pkt,
2673 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302674 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002675 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302676 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002677 "device-id": dh.device.Id,
2678 "packet": hex.EncodeToString(packetIn.Pkt),
2679 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002680 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002681
Matteo Scandolo92186242020-06-12 10:54:18 -07002682 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002683 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002684 "packet": hex.EncodeToString(packetIn.Pkt),
2685 "device-id": dh.device.Id,
2686 })
2687 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002688 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002689}
2690
Mahir Gunyela2e68702022-12-07 00:00:42 -08002691// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2692func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2693 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2694 if err != nil {
2695 return olterrors.NewErrInvalidValue(log.Fields{
2696 "egress-nni-port": egressPortNo,
2697 "device-id": dh.device.Id,
2698 }, err)
2699 }
2700 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2701
2702 if logger.V(log.DebugLevel) {
2703 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2704 "uplink-pkt": uplinkPkt,
2705 "packet": hex.EncodeToString(packet.Data),
2706 "device-id": dh.device.Id,
2707 })
2708 }
2709
2710 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2711 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2712 "packet": hex.EncodeToString(packet.Data),
2713 "device-id": dh.device.Id,
2714 }, err)
2715 }
2716 return nil
2717}
2718
2719// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2720func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2721 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2722 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2723 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2724 // Do not packet-out lldp packets on uni port.
2725 // ONOS has no clue about uni/nni ports, it just packets out on all
2726 // available ports on the Logical Switch. It should not be interested
2727 // in the UNI links.
2728 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2729 "device-id": dh.device.Id,
2730 })
2731 return nil
2732 }
2733 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2734 if innerEthType == 0x8100 {
2735 // q-in-q 802.1ad or 802.1q double tagged packet.
2736 // slice out the outer tag.
2737 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2738 if logger.V(log.DebugLevel) {
2739 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2740 "packet-data": hex.EncodeToString(packet.Data),
2741 "device-id": dh.device.Id,
2742 })
2743 }
2744 }
2745 }
2746 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2747 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2748 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2749 var gemPortID uint32
2750 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2751 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2752 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2753 }
2754 if err != nil {
2755 // In this case the openolt agent will receive the gemPortID as 0.
2756 // The agent tries to retrieve the gemPortID in this case.
2757 // This may not always succeed at the agent and packetOut may fail.
2758 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2759 "intf-id": intfID,
2760 "onu-id": onuID,
2761 "uni-id": uniID,
2762 "packet": hex.EncodeToString(packet.Data),
2763 "device-id": dh.device.Id,
2764 "error": err,
2765 })
2766 }
2767
2768 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2769 if logger.V(log.DebugLevel) {
2770 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2771 "egress-port-no": egressPortNo,
2772 "intf-id": intfID,
2773 "onu-id": onuID,
2774 "uni-id": uniID,
2775 "gem-port-id": gemPortID,
2776 "packet": hex.EncodeToString(packet.Data),
2777 "device-id": dh.device.Id,
2778 })
2779 }
2780
2781 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2782 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2783 "source": "adapter",
2784 "destination": "onu",
2785 "egress-port-number": egressPortNo,
2786 "intf-id": intfID,
2787 "oni-id": onuID,
2788 "uni-id": uniID,
2789 "gem-port-id": gemPortID,
2790 "packet": hex.EncodeToString(packet.Data),
2791 "device-id": dh.device.Id,
2792 }, err)
2793 }
2794 return nil
2795}
2796
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002797// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002798func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002799 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002800 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002801 "device-id": dh.device.Id,
2802 "egress-port-no": egressPortNo,
2803 "pkt-length": len(packet.Data),
2804 "packet": hex.EncodeToString(packet.Data),
2805 })
2806 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002807
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002808 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002809 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002810 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002811 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002812 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002813 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002814 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002815 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302816 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002817 "egressPortType": egressPortType,
2818 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302819 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002820 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002821 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002822 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002823}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002824
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002825func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2826 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002827}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302828
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002829func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002830
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002831 defer func() {
2832 dh.lockDevice.Lock()
2833 dh.isHeartbeatCheckActive = false
2834 dh.lockDevice.Unlock()
2835 }()
2836
2837 dh.lockDevice.Lock()
2838 dh.isHeartbeatCheckActive = true
2839 dh.lockDevice.Unlock()
2840
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302841 // start the heartbeat check towards the OLT.
2842 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302843 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302844
2845 for {
2846 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2847 select {
2848 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002849 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002850 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002851 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302852 if timerCheck == nil {
2853 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002854 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302855 }
2856 } else {
2857 if timerCheck != nil {
2858 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002859 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302860 }
2861 timerCheck = nil
2862 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302863 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2864 if dh.heartbeatSignature == 0 {
2865 // First time the signature will be 0, update the signture to DB when not found.
2866 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2867 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2868 }
2869 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2870
2871 dh.lockDevice.RLock()
2872 // Stop the read indication only if it the routine is active
2873 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2874 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2875 // on next execution of the readIndication routine.
2876 if !dh.isReadIndicationRoutineActive {
2877 // Start reading indications
2878 go func() {
2879 if err = dh.readIndications(ctx); err != nil {
2880 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2881 }
2882 }()
2883 }
2884 dh.lockDevice.RUnlock()
2885
2886 } else {
2887 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2888 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2889 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2890 go dh.updateStateRebooted(ctx)
2891 }
2892
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302893 }
2894 cancel()
2895 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002896 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302897 return
2898 }
2899 }
2900}
2901
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002902func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002903 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002904 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002905 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2906 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2907 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2908 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2909 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002910 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002911 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2912 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002913 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302914
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302915 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002916 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002917 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002918 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002919 DeviceId: dh.device.Id,
2920 OperStatus: voltha.OperStatus_UNKNOWN,
2921 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2922 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002923 _ = 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 -04002924 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302925 /*
2926 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2927 DeviceId: dh.device.Id,
2928 PortTypeFilter: 0,
2929 OperStatus: voltha.OperStatus_UNKNOWN,
2930 }); err != nil {
2931 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2932 }
2933 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002934
2935 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002936 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002937 cloned := proto.Clone(device).(*voltha.Device)
2938 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2939 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2940 dh.device = cloned // update local copy of the device
2941 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002942
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002943 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002944 // Stop the Stats collector
2945 if dh.isCollectorActive {
2946 dh.stopCollector <- true
2947 }
2948 // stop the heartbeat check routine
2949 if dh.isHeartbeatCheckActive {
2950 dh.stopHeartbeatCheck <- true
2951 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002952 // Stop the read indication only if it the routine is active
2953 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2954 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2955 // on next execution of the readIndication routine.
2956 if dh.isReadIndicationRoutineActive {
2957 dh.stopIndications <- true
2958 }
2959 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002960 dh.transitionMap.Handle(ctx, DeviceInit)
2961
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302962 }
2963}
kesavand39e0aa32020-01-28 20:58:50 -05002964
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302965func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2966 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2967 if err != nil || device == nil {
2968 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2969 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2970 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2971 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2972 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2973 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2974 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2975 return
2976 }
Mahir Gunyel701df862023-09-07 16:16:04 -07002977 //Starting the cleanup process
2978 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302979
2980 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2981 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2982 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2983 DeviceId: dh.device.Id,
2984 OperStatus: voltha.OperStatus_REBOOTED,
2985 ConnStatus: voltha.ConnectStatus_REACHABLE,
2986 }); err != nil {
2987 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2988 }
2989
2990 dh.lockDevice.RLock()
2991 // Stop the read indication only if it the routine is active
2992 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2993 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2994 // on next execution of the readIndication routine.
2995 if dh.isReadIndicationRoutineActive {
2996 dh.stopIndications <- true
2997 }
2998 dh.lockDevice.RUnlock()
2999
3000 //raise olt communication failure event
3001 raisedTs := time.Now().Unix()
3002 cloned := proto.Clone(device).(*voltha.Device)
3003 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
3004 cloned.OperStatus = voltha.OperStatus_UNKNOWN
3005 dh.device = cloned // update local copy of the device
3006 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
3007
Gustavo Silva41af9122022-10-11 11:05:13 -03003008 if err := dh.cleanupDeviceResources(ctx); err != nil {
3009 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
3010 } else {
3011 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
3012 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003013
3014 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303015 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003016 if dh.isCollectorActive {
3017 dh.stopCollector <- true
3018 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303019 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00003020 if dh.isHeartbeatCheckActive {
3021 dh.stopHeartbeatCheck <- true
3022 }
3023 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303024
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003025 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303026
3027 //reset adapter reconcile flag
3028 dh.adapterPreviouslyConnected = false
3029 for {
3030
3031 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
3032 if err != nil || childDevices == nil {
3033 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
3034 continue
3035 }
3036 if len(childDevices.Items) == 0 {
3037 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
3038 break
3039 } else {
3040 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
3041 time.Sleep(5 * time.Second)
3042 }
3043
3044 }
Mahir Gunyel701df862023-09-07 16:16:04 -07003045 //Cleanup completed , reset the flag
3046 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303047 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
3048 dh.transitionMap.Handle(ctx, DeviceInit)
3049
3050}
3051
kesavand39e0aa32020-01-28 20:58:50 -05003052// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003053func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
3054 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3055 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003056}
3057
3058// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3060 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3061 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003062}
3063
Mahir Gunyela2e68702022-12-07 00:00:42 -08003064// 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 +00003065func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3066 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003067 if port.GetType() == voltha.Port_ETHERNET_NNI {
3068 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303070 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303071 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003072 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003073 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003074 }
3075 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003076 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003077 ponIntf := &oop.Interface{IntfId: ponID}
3078 var operStatus voltha.OperStatus_Types
3079 if enablePort {
3080 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303081 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003082
3083 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303084 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003085 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003086 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003087 }
3088 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003089 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003090 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003091 } else {
3092 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303093 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003094 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303095 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003096 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003097 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003098 }
3099 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003100 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003101 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003102 }
khenaidoodc2116e2021-10-19 17:33:19 -04003103 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003104 DeviceId: dh.device.Id,
3105 PortType: voltha.Port_PON_OLT,
3106 PortNo: port.PortNo,
3107 OperStatus: operStatus,
3108 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303109 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303110 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003111 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003112 }
3113 return nil
3114}
3115
Mahir Gunyela2e68702022-12-07 00:00:42 -08003116// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003117func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003118 // Disable the port and update the oper_port_status to core
3119 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003120 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003121 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003122 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303123 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303124 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003125 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003126 }
3127 }
3128 }
3129 return nil
3130}
3131
Mahir Gunyela2e68702022-12-07 00:00:42 -08003132// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003133func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3134 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3135 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003136 if port.Type == voltha.Port_ETHERNET_NNI {
3137 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003138 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003139 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003140 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003141 }
3142 }
3143 if port.Type == voltha.Port_PON_OLT {
3144 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003145 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003146 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003147 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003148 }
3149 }
3150 }
3151}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003152
3153// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003154func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003155 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003156 if dh.getDeviceDeletionInProgressFlag() {
3157 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3158 // will reboot, so everything will be reset on the pOLT too.
3159 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3160 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3161 return nil
3162 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003163 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003164 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003165
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003166 var sn *oop.SerialNumber
3167 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003168 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303169 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003170 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303171 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003172 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003173 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003174
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003175 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003176 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003177 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003178 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3179 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3180 "device-id": dh.device.Id,
3181 "intf-id": intfID,
3182 "onuID": onuID,
3183 "err": err})
3184 } else {
3185 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003186 // Delete flows from device before schedulers and queue
3187 // Clear flowids for gem cache.
3188 removedFlows := []uint64{}
3189 for _, gem := range onuGem.GemPorts {
3190 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3191 for _, flowID := range flowIDs {
3192 //multiple gem port can have the same flow id
3193 //it is better to send only one flowRemove request to the agent
3194 var alreadyRemoved bool
3195 for _, removedFlowID := range removedFlows {
3196 if removedFlowID == flowID {
3197 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3198 alreadyRemoved = true
3199 break
3200 }
3201 }
3202 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003203 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003204 removedFlows = appendUnique64bit(removedFlows, flowID)
3205 }
3206 }
3207 }
3208 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3209 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003210 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3211 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3212 "device-id": dh.device.Id,
3213 "onu-device": onu,
3214 "err": err})
3215 }
yasin saplibddc2d72022-02-08 13:10:17 +00003216 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003217 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3218 "intf-id": intfID,
3219 "onu-device": onu,
3220 "onu-gem": onuGem,
3221 "err": err})
3222 //Not returning error on cleanup.
3223 }
3224 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05303225
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003226 }
yasin saplibddc2d72022-02-08 13:10:17 +00003227 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003228 dh.onus.Delete(onuKey)
3229 dh.discOnus.Delete(onuSn)
3230
3231 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003232 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303233 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303234 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003235 "onu-id": onuID}, err).Log()
3236 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003237
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003238 return nil
3239}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003240func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3241 flow := &oop.Flow{FlowId: flowID}
3242 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3243 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3244 "device-id": dh.device.Id})
3245 } else {
3246 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3247 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3248 "device-id": dh.device.Id,
3249 "err": err})
3250 }
3251 }
3252}
Girish Gowdracefae192020-03-19 18:14:10 -07003253
3254func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003255 for _, field := range flow_utils.GetOfbFields(flow) {
3256 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003257 return field.GetPort()
3258 }
3259 }
3260 return InvalidPort
3261}
3262
3263func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003264 for _, action := range flow_utils.GetActions(flow) {
3265 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003266 if out := action.GetOutput(); out != nil {
3267 return out.GetPort()
3268 }
3269 }
3270 }
3271 return InvalidPort
3272}
3273
Girish Gowdracefae192020-03-19 18:14:10 -07003274func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3275 inPort := getInPortFromFlow(flow)
3276 outPort := getOutPortFromFlow(flow)
3277
3278 if inPort == InvalidPort || outPort == InvalidPort {
3279 return inPort, outPort
3280 }
3281
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003282 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003283 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003284 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003285 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003286 return uniPort, outPort
3287 }
3288 }
3289 } else {
3290 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003291 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003292 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003293 return inPort, uniPort
3294 }
3295 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003296 } else if portType := plt.IntfIDToPortTypeName(inPort); 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 uniPort, outPort
3299 }
3300 }
3301 }
3302
3303 return InvalidPort, InvalidPort
3304}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003305
3306func extractOmciTransactionID(omciPkt []byte) uint16 {
3307 if len(omciPkt) > 3 {
3308 d := omciPkt[0:2]
3309 transid := binary.BigEndian.Uint16(d)
3310 return transid
3311 }
3312 return 0
3313}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003314
3315// StoreOnuDevice stores the onu parameters to the local cache.
3316func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3317 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3318 dh.onus.Store(onuKey, onuDevice)
3319}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003320
khenaidoodc2116e2021-10-19 17:33:19 -04003321func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003322 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003323 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003324 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003325 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003326 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003327 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003328 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003329 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3330 return nil, err
3331 }
3332 ID = device.ProxyAddress.GetOnuId()
3333 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3334 valueparam.Onu = &Onu
3335 valueparam.Value = value
3336
3337 // This API is unsupported until agent patch is added
3338 resp.Unsupported = uint32(value)
3339 _ = ctx
3340
3341 // Uncomment this code once agent changes are complete and tests
3342 /*
3343 resp, err = dh.Client.GetValue(ctx, valueparam)
3344 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003345 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003346 return nil, err
3347 }
3348 */
3349
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003350 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 -08003351 return resp, nil
3352}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003353
yasin saplid0566272021-12-21 09:10:30 +00003354func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
3355 // Default to NNI
3356 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003357 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003358 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003359 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003360 }
3361 return intfID
3362}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003363
Mahir Gunyelb0046752021-02-26 13:51:05 -08003364func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
3365 dh.perPonOnuIndicationChannelLock.Lock()
3366 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3367 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003368 return ch.indicationChannel
3369 }
3370 channels := onuIndicationChannels{
3371 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08003372 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003373 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003374 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003375 stopChannel: make(chan struct{}),
3376 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003377 dh.perPonOnuIndicationChannel[intfID] = channels
3378 dh.perPonOnuIndicationChannelLock.Unlock()
3379 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003380 return channels.indicationChannel
3381
3382}
3383
Mahir Gunyelb0046752021-02-26 13:51:05 -08003384func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3385 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3386 dh.perPonOnuIndicationChannelLock.Lock()
3387 defer dh.perPonOnuIndicationChannelLock.Unlock()
3388 for _, v := range dh.perPonOnuIndicationChannel {
3389 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003390 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003391 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003392}
3393
Mahir Gunyelb0046752021-02-26 13:51:05 -08003394func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3395 ind := onuIndicationMsg{
3396 ctx: ctx,
3397 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003398 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003399 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003400 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003401 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003402}
3403
Mahir Gunyelb0046752021-02-26 13:51:05 -08003404func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003405 for {
3406 select {
3407 // process one indication per onu, before proceeding to the next one
3408 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003409 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003410 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003411 "ind": indication})
3412 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003413 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003414 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003415 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3416 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003417 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003418 }
3419 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003420 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003421 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3422 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003423 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003424 }
3425 }
3426 case <-onuChannels.stopChannel:
3427 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3428 close(onuChannels.indicationChannel)
3429 return
3430 }
3431 }
3432}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003433
3434// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3435// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003436func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003437 if dh.getDeviceDeletionInProgressFlag() {
3438 // The device itself is going to be reset as part of deletion. So nothing to be done.
3439 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3440 return nil
3441 }
3442
Girish Gowdra491a9c62021-01-06 16:43:07 -08003443 // Step1 : Fill McastFlowOrGroupControlBlock
3444 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3445 // Step3 : Wait on response channel for response
3446 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003447 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003448 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3449 errChan := make(chan error)
3450 var groupID uint32
3451 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3452 ctx: ctx,
3453 flowOrGroupAction: action,
3454 flow: flow,
3455 group: group,
3456 errChan: &errChan,
3457 }
3458 if flow != nil {
3459 groupID = flow_utils.GetGroup(flow)
3460 } else if group != nil {
3461 groupID = group.Desc.GroupId
3462 } else {
3463 return errors.New("flow-and-group-both-nil")
3464 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003465 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3466 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3467 // Derive the appropriate go routine to handle the request by a simple module operation.
3468 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3469 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3470 // Wait for handler to return error value
3471 err := <-errChan
3472 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3473 return err
3474 }
3475 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3476 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003477}
3478
3479// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003480func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003481 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003482 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003483 // block on the channel to receive an incoming mcast flow/group
3484 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003485 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3486 if mcastFlowOrGroupCb.flow != nil {
3487 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3488 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3489 log.Fields{"device-id": dh.device.Id,
3490 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003491 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3492 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3493 for _, flMgr := range dh.flowMgr {
3494 if flMgr != nil {
3495 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3496 break
3497 }
3498 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003499 // Pass the return value over the return channel
3500 *mcastFlowOrGroupCb.errChan <- err
3501 } else { // flow remove
3502 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3503 log.Fields{"device-id": dh.device.Id,
3504 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003505 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3506 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3507 for _, flMgr := range dh.flowMgr {
3508 if flMgr != nil {
3509 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3510 break
3511 }
3512 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003513 // Pass the return value over the return channel
3514 *mcastFlowOrGroupCb.errChan <- err
3515 }
3516 } else { // mcast group
3517 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3518 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3519 log.Fields{"device-id": dh.device.Id,
3520 "groupToAdd": mcastFlowOrGroupCb.group})
3521 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3522 // Pass the return value over the return channel
3523 *mcastFlowOrGroupCb.errChan <- err
3524 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3525 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3526 log.Fields{"device-id": dh.device.Id,
3527 "groupToModify": mcastFlowOrGroupCb.group})
3528 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3529 // Pass the return value over the return channel
3530 *mcastFlowOrGroupCb.errChan <- err
3531 } else { // group remove
3532 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3533 log.Fields{"device-id": dh.device.Id,
3534 "groupToRemove": mcastFlowOrGroupCb.group})
3535 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3536 // Pass the return value over the return channel
3537 *mcastFlowOrGroupCb.errChan <- err
3538 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003539 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003540 case <-stopHandler:
3541 dh.mcastHandlerRoutineActive[routineIndex] = false
3542 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003543 }
3544 }
3545}
kesavand62126212021-01-12 04:56:06 -05003546
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003547// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003548func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003549 for i, v := range dh.stopMcastHandlerRoutine {
3550 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003551 select {
3552 case v <- true:
3553 case <-time.After(time.Second * 5):
3554 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3555 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003556 }
3557 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003558
3559 if dh.incomingMcastFlowOrGroup != nil {
3560 for k := range dh.incomingMcastFlowOrGroup {
3561 if dh.incomingMcastFlowOrGroup[k] != nil {
3562 dh.incomingMcastFlowOrGroup[k] = nil
3563 }
3564 }
3565 dh.incomingMcastFlowOrGroup = nil
3566 }
3567
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003568 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003569 logger.Debug(ctx, "stopped all mcast handler routines")
3570}
3571
kesavand62126212021-01-12 04:56:06 -05003572func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3573
3574 singleValResp := extension.SingleGetValueResponse{
3575 Response: &extension.GetValueResponse{
3576 Response: &extension.GetValueResponse_PortCoutners{
3577 PortCoutners: &extension.GetOltPortCountersResponse{},
3578 },
3579 },
3580 }
3581
3582 errResp := func(status extension.GetValueResponse_Status,
3583 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3584 return &extension.SingleGetValueResponse{
3585 Response: &extension.GetValueResponse{
3586 Status: status,
3587 ErrReason: reason,
3588 },
3589 }
3590 }
3591
3592 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3593 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3594 //send error response
3595 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3596 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3597 }
3598 statIndChn := make(chan bool, 1)
3599 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3600 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3601 //request openOlt agent to send the the port statistics indication
3602
3603 go func() {
3604 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3605 if err != nil {
3606 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3607 }
3608 }()
3609 select {
3610 case <-statIndChn:
3611 //indication received for ports stats
3612 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3613 case <-time.After(oltPortInfoTimeout * time.Second):
3614 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3615 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3616 case <-ctx.Done():
3617 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3618 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3619 }
3620 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3621 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003622 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003623 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3624 cmnni := dh.portStats.collectNNIMetrics(intfID)
3625 if cmnni == nil {
3626 //TODO define the error reason
3627 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3628 }
3629 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3630 return &singleValResp
3631
3632 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3633 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003634 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003635 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3636 cmpon := dh.portStats.collectPONMetrics(intfID)
3637 if cmpon == nil {
3638 //TODO define the error reason
3639 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3640 }
3641 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3642 return &singleValResp
3643 }
3644 }
3645 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3646}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303647
3648func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3649
3650 singleValResp := extension.SingleGetValueResponse{
3651 Response: &extension.GetValueResponse{
3652 Response: &extension.GetValueResponse_OnuPonCounters{
3653 OnuPonCounters: &extension.GetOnuCountersResponse{},
3654 },
3655 },
3656 }
3657
3658 errResp := func(status extension.GetValueResponse_Status,
3659 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3660 return &extension.SingleGetValueResponse{
3661 Response: &extension.GetValueResponse{
3662 Status: status,
3663 ErrReason: reason,
3664 },
3665 }
3666 }
3667 intfID := onuPonInfo.IntfId
3668 onuID := onuPonInfo.OnuId
3669 onuKey := dh.formOnuKey(intfID, onuID)
3670
3671 if _, ok := dh.onus.Load(onuKey); !ok {
3672 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3673 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3674 }
3675 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3676 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3677 if cmnni == nil {
3678 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3679 }
3680 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3681 return &singleValResp
3682
3683}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003684
nikesh.krishnanc8473432023-06-14 12:14:54 +05303685func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
3686
3687 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3688 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3689 if err != nil {
3690 return nil, err
3691 }
3692 return OnuInfo, nil
3693
3694}
3695
3696func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
3697
3698 Intf := oop.Interface{IntfId: intfID}
3699 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3700 if err != nil {
3701 return nil, err
3702 }
3703 return IntfInfo, nil
3704
3705}
3706
Gamze Abaka85e9a142021-05-26 13:41:39 +00003707func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3708
3709 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3710 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3711 if err != nil {
3712 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3713 return generateSingleGetValueErrorResponse(err)
3714 }
3715 return &extension.SingleGetValueResponse{
3716 Response: &extension.GetValueResponse{
3717 Status: extension.GetValueResponse_OK,
3718 Response: &extension.GetValueResponse_RxPower{
3719 RxPower: &extension.GetRxPowerResponse{
3720 IntfId: rxPowerRequest.IntfId,
3721 OnuId: rxPowerRequest.OnuId,
3722 Status: rxPower.Status,
3723 FailReason: rxPower.FailReason.String(),
3724 RxPower: rxPower.RxPowerMeanDbm,
3725 },
3726 },
3727 },
3728 }
3729}
3730
praneeth nalmas55616d62023-02-06 09:19:18 +05303731func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
3732
3733 errResp := func(status extension.GetValueResponse_Status,
3734 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3735 return &extension.SingleGetValueResponse{
3736 Response: &extension.GetValueResponse{
3737 Status: status,
3738 ErrReason: reason,
3739 },
3740 }
3741 }
3742
3743 resp := extension.SingleGetValueResponse{
3744 Response: &extension.GetValueResponse{
3745 Status: extension.GetValueResponse_OK,
3746 Response: &extension.GetValueResponse_OltRxPower{
3747 OltRxPower: &extension.GetOltRxPowerResponse{},
3748 },
3749 },
3750 }
3751
3752 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3753 portLabel := OltRxPowerRequest.PortLabel
3754 serialNumber := OltRxPowerRequest.OnuSn
3755
3756 portInfo := strings.Split(portLabel, "-")
3757 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3758
3759 if err != nil {
3760 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3761 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3762 }
3763
3764 if portInfo[0] != "pon" {
3765 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3766 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3767 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303768
3769 if serialNumber != "" {
3770
3771 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3772 if onuDev != nil {
3773
3774 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3775 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3776 if err != nil {
3777
3778 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3779 return generateSingleGetValueErrorResponse(err)
3780
3781 }
3782
3783 rxPowerValue := extension.RxPower{}
3784 rxPowerValue.OnuSn = onuDev.serialNumber
3785 rxPowerValue.Status = rxPower.GetStatus()
3786 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3787 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3788
3789 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3790
3791 } else {
3792
3793 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3794 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3795 }
3796
3797 } else {
3798
3799 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303800 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth nalmas55616d62023-02-06 09:19:18 +05303801
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303802 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05303803 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3804 if err != nil {
3805 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3806 } else {
3807
3808 rxPowerValue := extension.RxPower{}
3809 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3810 rxPowerValue.Status = rxPower.GetStatus()
3811 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3812 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3813
3814 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3815 }
3816
3817 }
3818 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3819 return true
3820 })
3821 }
3822 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3823 return &resp
3824}
3825
Gamze Abaka85e9a142021-05-26 13:41:39 +00003826func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3827 errResp := func(status extension.GetValueResponse_Status,
3828 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3829 return &extension.SingleGetValueResponse{
3830 Response: &extension.GetValueResponse{
3831 Status: status,
3832 ErrReason: reason,
3833 },
3834 }
3835 }
3836
3837 if err != nil {
3838 if e, ok := status.FromError(err); ok {
3839 switch e.Code() {
3840 case codes.Internal:
3841 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3842 case codes.DeadlineExceeded:
3843 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3844 case codes.Unimplemented:
3845 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3846 case codes.NotFound:
3847 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3848 }
3849 }
3850 }
3851
3852 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3853}
khenaidoo106c61a2021-08-11 18:05:46 -04003854
3855/*
3856Helper functions to communicate with Core
3857*/
3858
3859func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3860 cClient, err := dh.coreClient.GetCoreServiceClient()
3861 if err != nil || cClient == nil {
3862 return nil, err
3863 }
3864 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3865 defer cancel()
3866 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3867}
3868
khenaidoodc2116e2021-10-19 17:33:19 -04003869func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003870 cClient, err := dh.coreClient.GetCoreServiceClient()
3871 if err != nil || cClient == nil {
3872 return nil, err
3873 }
3874 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3875 defer cancel()
3876 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3877}
3878
khenaidoodc2116e2021-10-19 17:33:19 -04003879func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003880 cClient, err := dh.coreClient.GetCoreServiceClient()
3881 if err != nil || cClient == nil {
3882 return err
3883 }
3884 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3885 defer cancel()
3886 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3887 return err
3888}
3889
3890func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3891 cClient, err := dh.coreClient.GetCoreServiceClient()
3892 if err != nil || cClient == nil {
3893 return nil, err
3894 }
3895 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3896 defer cancel()
3897 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3898}
3899
3900func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3901 cClient, err := dh.coreClient.GetCoreServiceClient()
3902 if err != nil || cClient == nil {
3903 return nil, err
3904 }
3905 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3906 defer cancel()
3907 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3908}
3909
3910func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3911 cClient, err := dh.coreClient.GetCoreServiceClient()
3912 if err != nil || cClient == nil {
3913 return err
3914 }
3915 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3916 defer cancel()
3917 _, err = cClient.DeviceUpdate(subCtx, device)
3918 return err
3919}
3920
khenaidoodc2116e2021-10-19 17:33:19 -04003921func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003922 cClient, err := dh.coreClient.GetCoreServiceClient()
3923 if err != nil || cClient == nil {
3924 return nil, err
3925 }
3926 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3927 defer cancel()
3928 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3929}
3930
khenaidoodc2116e2021-10-19 17:33:19 -04003931func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003932 cClient, err := dh.coreClient.GetCoreServiceClient()
3933 if err != nil || cClient == nil {
3934 return err
3935 }
3936 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3937 defer cancel()
3938 _, err = cClient.SendPacketIn(subCtx, pkt)
3939 return err
3940}
3941
3942func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3943 cClient, err := dh.coreClient.GetCoreServiceClient()
3944 if err != nil || cClient == nil {
3945 return err
3946 }
3947 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3948 defer cancel()
3949 _, err = cClient.PortCreated(subCtx, port)
3950 return err
3951}
3952
khenaidoodc2116e2021-10-19 17:33:19 -04003953func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003954 cClient, err := dh.coreClient.GetCoreServiceClient()
3955 if err != nil || cClient == nil {
3956 return err
3957 }
3958 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3959 defer cancel()
3960 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3961 return err
3962}
3963
khenaidoodc2116e2021-10-19 17:33:19 -04003964func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003965 cClient, err := dh.coreClient.GetCoreServiceClient()
3966 if err != nil || cClient == nil {
3967 return err
3968 }
3969 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3970 defer cancel()
3971 _, err = cClient.PortStateUpdate(subCtx, portState)
3972 return err
3973}
3974
khenaidoodc2116e2021-10-19 17:33:19 -04003975func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003976 cClient, err := dh.coreClient.GetCoreServiceClient()
3977 if err != nil || cClient == nil {
3978 return nil, err
3979 }
3980 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3981 defer cancel()
3982 return cClient.GetDevicePort(subCtx, portFilter)
3983}
3984
nikesh.krishnanc8473432023-06-14 12:14:54 +05303985func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
3986 cClient, err := dh.coreClient.GetCoreServiceClient()
3987 if err != nil || cClient == nil {
3988 return nil, err
3989 }
3990 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3991 defer cancel()
3992 return cClient.GetPorts(subCtx, portFilter)
3993}
3994
khenaidoo106c61a2021-08-11 18:05:46 -04003995/*
3996Helper functions to communicate with child adapter
3997*/
3998
khenaidoodc2116e2021-10-19 17:33:19 -04003999func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004000 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4001 if err != nil || aClient == nil {
4002 return err
4003 }
4004 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
4005 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4006 defer cancel()
4007 _, err = aClient.OmciIndication(subCtx, response)
4008 return err
4009}
4010
khenaidoodc2116e2021-10-19 17:33:19 -04004011func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004012 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4013 if err != nil || aClient == nil {
4014 return err
4015 }
4016 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
4017 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4018 defer cancel()
4019 _, err = aClient.OnuIndication(subCtx, onuInd)
4020 return err
4021}
4022
khenaidoodc2116e2021-10-19 17:33:19 -04004023func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004024 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4025 if err != nil || aClient == nil {
4026 return err
4027 }
4028 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
4029 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4030 defer cancel()
4031 _, err = aClient.DeleteTCont(subCtx, tContInfo)
4032 return err
4033}
4034
khenaidoodc2116e2021-10-19 17:33:19 -04004035func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004036 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4037 if err != nil || aClient == nil {
4038 return err
4039 }
4040 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
4041 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4042 defer cancel()
4043 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
4044 return err
4045}
4046
khenaidoodc2116e2021-10-19 17:33:19 -04004047func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04004048 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
4049 if err != nil || aClient == nil {
4050 return err
4051 }
4052 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
4053 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
4054 defer cancel()
4055 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4056 return err
4057}
4058
4059/*
4060Helper functions for remote communication
4061*/
4062
4063// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4064// supports is deleted
4065func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4066 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4067
4068 dh.lockChildAdapterClients.Lock()
4069 defer dh.lockChildAdapterClients.Unlock()
4070 if _, ok := dh.childAdapterClients[endpoint]; ok {
4071 // Already set
4072 return nil
4073 }
4074
4075 // Setup child's adapter grpc connection
4076 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004077 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4078 dh.cfg.AdapterEndpoint,
4079 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004080 "onu_inter_adapter_service.OnuInterAdapterService",
4081 dh.onuInterAdapterRestarted,
4082 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004083 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4084 return err
4085 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304086 retryCodes := []codes.Code{
4087 codes.Unavailable, // server is currently unavailable
4088 codes.DeadlineExceeded, // deadline for the operation was exceeded
4089 }
4090 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4091 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 -04004092
nikesh.krishnand9812542023-08-01 18:31:39 +05304093 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004094 // Wait until we have a connection to the child adapter.
4095 // Unlimited retries or until context expires
4096 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4097 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4098 for {
4099 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4100 if err == nil && client != nil {
4101 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4102 break
4103 }
4104 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4105 // Backoff
4106 if err = backoff.Backoff(subCtx); err != nil {
4107 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4108 break
4109 }
4110 }
4111 return nil
4112}
4113
khenaidoodc2116e2021-10-19 17:33:19 -04004114func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004115
4116 // First check from cache
4117 dh.lockChildAdapterClients.RLock()
4118 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4119 dh.lockChildAdapterClients.RUnlock()
4120 return cgClient.GetOnuInterAdapterServiceClient()
4121 }
4122 dh.lockChildAdapterClients.RUnlock()
4123
4124 // Set the child connection - can occur on restarts
4125 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4126 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4127 cancel()
4128 if err != nil {
4129 return nil, err
4130 }
4131
4132 // Get the child client now
4133 dh.lockChildAdapterClients.RLock()
4134 defer dh.lockChildAdapterClients.RUnlock()
4135 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4136 return cgClient.GetOnuInterAdapterServiceClient()
4137 }
4138 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4139}
4140
4141func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4142 dh.lockChildAdapterClients.Lock()
4143 defer dh.lockChildAdapterClients.Unlock()
4144 for key, client := range dh.childAdapterClients {
4145 client.Stop(ctx)
4146 delete(dh.childAdapterClients, key)
4147 }
4148}
4149
khenaidooefff76e2021-12-15 16:51:30 -05004150// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4151func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4152 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004153 return nil
4154}
4155
khenaidooefff76e2021-12-15 16:51:30 -05004156// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4157func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4158 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004159 return nil
4160 }
khenaidooefff76e2021-12-15 16:51:30 -05004161 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004162}
Girish Gowdra950326e2021-11-05 12:43:24 -07004163
4164func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4165 dh.lockDevice.Lock()
4166 defer dh.lockDevice.Unlock()
4167 dh.isDeviceDeletionInProgress = flag
4168}
4169
4170func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4171 dh.lockDevice.RLock()
4172 defer dh.lockDevice.RUnlock()
4173 return dh.isDeviceDeletionInProgress
4174}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004175
4176// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4177// Returns false if waiting timed out.
4178func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4179 c := make(chan struct{})
4180 go func() {
4181 defer close(c)
4182 wg.Wait()
4183 }()
4184 select {
4185 case <-c:
4186 return true // completed normally
4187 case <-time.After(timeout):
4188 return false // timed out
4189 }
4190}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304191
4192func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4193 val, err := json.Marshal(signature)
4194 if err != nil {
4195 logger.Error(ctx, "failed-to-marshal")
4196 return
4197 }
4198 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4199 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4200 }
4201}
4202
4203func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4204 var signature uint32
4205
4206 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4207 if er == nil {
4208 if Value != nil {
4209 Val, er := kvstore.ToByte(Value.Value)
4210 if er != nil {
4211 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4212 return signature
4213 }
4214 if er = json.Unmarshal(Val, &signature); er != nil {
4215 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4216 return signature
4217 }
4218 }
4219 }
4220 return signature
4221}