blob: 22c78528be8ebf8cda857056796aa802e627bc15 [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
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700135}
136
Mahir Gunyela2e68702022-12-07 00:00:42 -0800137// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700138type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400139 deviceID string
140 deviceType string
141 serialNumber string
142 onuID uint32
143 intfID uint32
144 proxyDeviceID string
145 losRaised bool
146 rdiRaised bool
147 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700148}
149
Mahir Gunyelb0046752021-02-26 13:51:05 -0800150type onuIndicationMsg struct {
151 ctx context.Context
152 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800153}
154
155type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800156 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800157 stopChannel chan struct{}
158}
159
Mahir Gunyela2e68702022-12-07 00:00:42 -0800160// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
161// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
162// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
163// 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 -0800164type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400165 ctx context.Context // Flow/group handler context
166 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
167 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
168 group *of.OfpGroupEntry // Group message (can be nil or valid group)
169 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800170}
171
Naga Manjunath7615e552019-10-11 22:35:47 +0530172var pmNames = []string{
173 "rx_bytes",
174 "rx_packets",
175 "rx_mcast_packets",
176 "rx_bcast_packets",
177 "tx_bytes",
178 "tx_packets",
179 "tx_mcast_packets",
180 "tx_bcast_packets",
181}
182
Mahir Gunyela2e68702022-12-07 00:00:42 -0800183// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400184func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700185 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700186 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700187 device.deviceType = deviceTp
188 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700189 device.onuID = onuID
190 device.intfID = intfID
191 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530192 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400193 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700194 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530195}
196
Mahir Gunyela2e68702022-12-07 00:00:42 -0800197// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400198func 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 -0700199 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530200 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800201 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400202 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400203 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700204 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700205 dh.device = cloned
206 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500207 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700208 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000209 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
210 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530211 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 -0500212 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800213 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800214 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400215 dh.childAdapterClients = make(map[string]*vgrpc.Client)
216 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300217 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530218 if dh.kvStore == nil {
219 logger.Error(ctx, "Failed to setup KV store")
220 return nil
221 }
222
Girish Gowdra491a9c62021-01-06 16:43:07 -0800223 // Create a slice of buffered channels for handling concurrent mcast flow/group.
224 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700225 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
226 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800227 for i := range dh.incomingMcastFlowOrGroup {
228 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800229 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800230 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
231 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
232 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
233 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700234 dh.mcastHandlerRoutineActive[i] = true
235 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800236 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700237 //TODO initialize the support classes.
238 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530239}
240
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530241func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
242 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
243 switch storeType {
244 case "etcd":
245 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
246 }
247 return nil, errors.New("unsupported-kv-store")
248}
249
250// SetKVClient sets the KV client and return a kv backend
251func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
252 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
253 if err != nil {
254 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
255 return nil
256 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530257 kvbackend := &db.Backend{
258 Client: kvClient,
259 StoreType: backend,
260 Address: addr,
261 Timeout: rsrcMgr.KvstoreTimeout,
262 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
263
264 return kvbackend
265}
266
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000267// CloseKVClient closes open KV clients
268func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
269 if dh.resourceMgr != nil {
270 for _, rscMgr := range dh.resourceMgr {
271 if rscMgr != nil {
272 rscMgr.CloseKVClient(ctx)
273 }
274 }
275 }
276 if dh.flowMgr != nil {
277 for _, flMgr := range dh.flowMgr {
278 if flMgr != nil {
279 flMgr.CloseKVClient(ctx)
280 }
281 }
282 }
283}
284
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530285// start save the device to the data model
286func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700287 dh.lockDevice.Lock()
288 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000289 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700290 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000291 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530292}
293
khenaidooefff76e2021-12-15 16:51:30 -0500294// Stop stops the device handler
295func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700296 dh.lockDevice.Lock()
297 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000298 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500299 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400300
khenaidooefff76e2021-12-15 16:51:30 -0500301 // Delete (which will stop also) all grpc connections to the child adapters
302 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000303 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530304}
305
ssiddiqui04386ee2021-08-23 21:58:25 +0530306func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
307 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
308 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
309 if pooledIntfID == intfID {
310 return resourceRanges.GetTechnology()
311 }
312 }
313 }
314 return ""
315}
316
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400317func macifyIP(ip net.IP) string {
318 if len(ip) > 0 {
319 oct1 := strconv.FormatInt(int64(ip[12]), 16)
320 oct2 := strconv.FormatInt(int64(ip[13]), 16)
321 oct3 := strconv.FormatInt(int64(ip[14]), 16)
322 oct4 := strconv.FormatInt(int64(ip[15]), 16)
323 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
324 }
325 return ""
326}
327
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400329 var genmac string
330 var addr net.IP
331 var ips []string
332 var err error
333
Neha Sharma96b7bf22020-06-15 10:37:32 +0000334 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400335
336 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000337 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400338
339 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000340 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400341 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000342 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400343 }
344 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000345 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530346 log.Fields{"host": ips[0],
347 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400348 return genmac, nil
349 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000350 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400351 }
352
353 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000354 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530355 log.Fields{"host": host,
356 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400357 return genmac, nil
358}
359
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530360func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700361 slist := strings.Split(mac, ":")
362 result := make([]uint32, len(slist))
363 var err error
364 var tmp int64
365 for index, val := range slist {
366 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
367 return []uint32{1, 2, 3, 4, 5, 6}
368 }
369 result[index] = uint32(tmp)
370 }
371 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530372}
373
Mahir Gunyela2e68702022-12-07 00:00:42 -0800374// 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 -0800375func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530376
David K. Bainbridge794735f2020-02-11 21:01:37 -0800377 switch portType {
378 case voltha.Port_ETHERNET_NNI:
379 return fmt.Sprintf("nni-%d", portNum), nil
380 case voltha.Port_PON_OLT:
381 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700382 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800383
Girish Kumarf26e4882020-03-05 06:49:10 +0000384 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530385}
386
Elia Battiston596406d2022-02-02 12:19:00 +0100387func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
388 if speedMbps == 0 {
389 //In case it was not set in the indication
390 //and no other value was provided
391 speedMbps = defaultPortSpeedMbps
392 }
393
394 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
395 switch speedMbps {
396 case 1000000:
397 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
398 case 100000:
399 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
400 case 40000:
401 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
402 case 10000:
403 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
404 case 1000:
405 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
406 case 100:
407 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
408 case 10:
409 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
410 }
411
412 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
413
414 port := &of.OfpPort{
415 HwAddr: macAddressToUint32Array(macAddress),
416 Config: 0,
417 State: uint32(of.OfpPortState_OFPPS_LIVE),
418 Curr: capacity,
419 Advertised: capacity,
420 Peer: capacity,
421 CurrSpeed: speedMbps * 1000, //kbps
422 MaxSpeed: speedMbps * 1000, //kbps
423 }
424
425 return port
426}
427
428func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000429 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700430 if state == "up" {
431 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500432 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500433 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700434 } else {
435 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500436 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700437 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700438 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400439 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800440 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000441 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400442 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500443
khenaidoo106c61a2021-08-11 18:05:46 -0400444 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400445 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400446 DeviceId: dh.device.Id,
447 Port: portNum,
448 })
449 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000450 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400451 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400452 DeviceId: dh.device.Id,
453 PortType: portType,
454 PortNo: portNum,
455 OperStatus: operStatus})
456 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400457 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
458 "device-id": dh.device.Id,
459 "port-type": portType,
460 "port-number": portNum,
461 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500462 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400463 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500464 }
khenaidoo106c61a2021-08-11 18:05:46 -0400465
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400466 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400467 port = &voltha.Port{
468 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700469 PortNo: portNum,
470 Label: label,
471 Type: portType,
472 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100473 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700474 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000475 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700476 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400477 err = dh.createPortInCore(ctx, port)
478 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000479 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800480 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000481 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400482 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000483 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530484 return nil
485}
486
Kent Hagermane6ff1012020-07-14 15:07:53 -0400487func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400488 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530489 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400490 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
491 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530492 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800493 dh.lockDevice.Lock()
494 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530495 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530496}
497
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700498// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530499// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800500func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000501 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700502 defer func() {
503 dh.lockDevice.Lock()
504 dh.isReadIndicationRoutineActive = false
505 dh.lockDevice.Unlock()
506 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700507 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700508 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700509 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700510 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400511
David Bainbridgef5879ca2019-12-13 21:17:54 +0000512 // Create an exponential backoff around re-enabling indications. The
513 // maximum elapsed time for the back off is set to 0 so that we will
514 // continue to retry. The max interval defaults to 1m, but is set
515 // here for code clarity
516 indicationBackoff := backoff.NewExponentialBackOff()
517 indicationBackoff.MaxElapsedTime = 0
518 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700519
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700520 dh.lockDevice.Lock()
521 dh.isReadIndicationRoutineActive = true
522 dh.lockDevice.Unlock()
523
Girish Gowdra3f974912020-03-23 20:35:18 -0700524Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700525 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400526 select {
527 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000528 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700529 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400530 default:
531 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100532
533 select {
534 case <-indications.Context().Done():
535 if err != nil {
536 logger.Warnw(ctx, "error-during-enable-indications",
537 log.Fields{"err": err,
538 "device-id": dh.device.Id})
539 }
540
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400541 // Use an exponential back off to prevent getting into a tight loop
542 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100543 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
544 "device-id": dh.device.Id,
545 "duration": duration,
546 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400547 if duration == backoff.Stop {
548 // If we reach a maximum then warn and reset the backoff
549 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100550 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530551 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530552 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400553 indicationBackoff.Reset()
554 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700555
556 // On failure process a backoff timer while watching for stopIndications
557 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700558 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700559 select {
560 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000561 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700562 if !backoffTimer.Stop() {
563 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700564 }
565 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700566 case <-backoffTimer.C:
567 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700568 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700569 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
570 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400571 }
572 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100573 default:
574 if err != nil {
575 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530576 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530577 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100578 // Close the stream, and re-initialize it
579 if err = indications.CloseSend(); err != nil {
580 // Ok to ignore here, because we landed here due to a problem on the stream
581 // In all probability, the closeSend call may fail
582 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
583 log.Fields{"err": err,
584 "device-id": dh.device.Id})
585 }
586 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
587 return err
588 }
589 // once we re-initialized the indication stream, continue to read indications
590 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700591 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100592 // Reset backoff if we have a successful receive
593 indicationBackoff.Reset()
594 // When OLT is admin down, ignore all indications.
595 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
596 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
597 log.Fields{"indication": indication,
598 "device-id": dh.device.Id})
599 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700600 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100601 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530602 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700603 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700604 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700605 // Close the send stream
606 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700607
Girish Gowdra3f974912020-03-23 20:35:18 -0700608 return nil
609}
610
611func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700612 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700613 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
614 if err != nil {
615 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
616 }
617 if indications == nil {
618 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
619 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700620 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700621 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400622}
623
624// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
625func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
626 switch indication.Data.(type) {
627 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
628 return true
629
630 default:
631 return false
632 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633}
634
David K. Bainbridge794735f2020-02-11 21:01:37 -0800635func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700636 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000637 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530638 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700639 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530640 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700641 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000642 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000643 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530644 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000645 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800646 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000647 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800648 }
649 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650}
651
David K. Bainbridge794735f2020-02-11 21:01:37 -0800652// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530653func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700654 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 switch indication.Data.(type) {
656 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000657 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
658 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700659 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 -0800660 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400661 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800662 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700663 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000664 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
665 defer span.Finish()
666
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700667 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800668 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100669 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400670 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 }
672 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000673 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700674 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000675 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
676 defer span.Finish()
677
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700678 intfOperInd := indication.GetIntfOperInd()
679 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800680 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100681 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400682 _ = 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 -0800683 }
684 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700685 } else if intfOperInd.GetType() == "pon" {
686 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
687 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800688 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100689 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400690 _ = 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 -0800691 }
692 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000693 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700694 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000695 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530696 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530697 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700698 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000699 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
700 defer span.Finish()
701
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700702 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000703 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800704 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800705 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700706 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000707 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
708 defer span.Finish()
709
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000711 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800712 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800713 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700714 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000715 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
716 defer span.Finish()
717
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700718 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000719 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 -0800720 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000721 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400722 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800723 }
724 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700725 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000726 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
727 defer span.Finish()
728
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700729 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000730 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700731 "intf-type": pktInd.IntfId,
732 "intf-id": pktInd.IntfId,
733 "gem-port-id": pktInd.GemportId,
734 "port-no": pktInd.PortNo,
735 "device-id": dh.device.Id,
736 })
737
738 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000739 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700740 "intf-type": pktInd.IntfId,
741 "intf-id": pktInd.IntfId,
742 "gem-port-id": pktInd.GemportId,
743 "port-no": pktInd.PortNo,
744 "packet": hex.EncodeToString(pktInd.Pkt),
745 "device-id": dh.device.Id,
746 })
747 }
748
David K. Bainbridge794735f2020-02-11 21:01:37 -0800749 go func() {
750 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400751 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800752 }
753 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700754 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000755 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
756 defer span.Finish()
757
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700758 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700759 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700760 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000761 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
762 defer span.Finish()
763
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700764 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000765 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700766 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000767 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
768 defer span.Finish()
769
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700770 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000771 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
772 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700773 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530774}
775
nikesh.krishnanc8473432023-06-14 12:14:54 +0530776func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
777 onuInd := &oop.OnuIndication{
778 IntfId: intfID,
779 OnuId: onuID,
780 OperState: operState,
781 AdminState: adminState,
782 }
783 indication := &oop.Indication{
784 Data: &oop.Indication_OnuInd{
785 OnuInd: onuInd,
786 },
787 }
788 return indication
789}
790
791func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
792 onuAlarmInd := &oop.OnuAlarmIndication{
793 IntfId: intfID,
794 OnuId: onuID,
795 LosStatus: losStatus,
796 }
797 alarmInd := &oop.AlarmIndication{
798 Data: &oop.AlarmIndication_OnuAlarmInd{
799 OnuAlarmInd: onuAlarmInd,
800 },
801 }
802 return alarmInd
803}
804func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
805
806 ponlosAlarmInd := &oop.LosIndication{
807 IntfId: intfID,
808 Status: losStatus,
809 }
810 alarmInd := &oop.AlarmIndication{
811 Data: &oop.AlarmIndication_LosInd{
812 LosInd: ponlosAlarmInd,
813 },
814 }
815 return alarmInd
816}
817func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
818 go func() {
819 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
820 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
821 }
822 }()
823
824 raisedTs := time.Now().Unix()
825 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
826}
827
828func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
829
830 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
831 if err != nil {
832
833 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
834
835 return err
836 }
837 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
838
839 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
840 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
841 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
842
843 onuID := onuDeviceFromCore.ProxyAddress.OnuId
844 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
845 if err != nil {
846 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
847
848 } else {
849 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
850 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
851 switch {
852 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
853 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
854 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
855
856 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
857 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") //check bal cli login notepad
858 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
859 raisedTs := time.Now().Unix()
860 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
861
862 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
863 }
864
865 }
866
867 }
868
869 return nil
870}
871
872func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
873 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
874 DeviceId: dh.device.Id,
875 PortType: voltha.Port_PON_OLT,
876 })
877 if err != nil {
878 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
879
880 return err
881
882 }
883 for _, portFromCore := range portsFromCore.Items {
884 portNum := portFromCore.GetPortNo()
885 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
886 portOperStatusFromCore := portFromCore.OperStatus
887 portAdminStateFromCore := portFromCore.AdminState
888 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
889 if err != nil {
890 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
891 } else {
892 portLosFromOlt := ponPortFromOlt.GetLos()
893 portStateFromOlt := ponPortFromOlt.GetState()
894 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
895 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
896 "portStateFromOlt": portStateFromOlt.String(),
897 "portOperStatusFromCore": portOperStatusFromCore.String(),
898 "device-id": dh.device.Id,
899 "port": portNum})
900 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
901 raisedTs := time.Now().Unix()
902 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
903
904 }
905 switch {
906 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
907 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
908 "portStateFromOlt": portStateFromOlt.String(),
909 "portOperStatusFromCore": portOperStatusFromCore.String(),
910 "device-id": dh.device.Id,
911 "port": portNum})
912 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
913 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
914 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
915 "portStateFromOlt": portStateFromOlt.String(),
916 "portOperStatusFromCore": portOperStatusFromCore.String(),
917 "device-id": dh.device.Id,
918 "port": portNum})
919 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
920 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
921 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
922 "device-id": dh.device.Id,
923 "port": portNum})
924 default:
925 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
926 "portStateFromOlt": portStateFromOlt.String(),
927 "portOperStatusFromCore": portOperStatusFromCore.String(),
928 "device-id": dh.device.Id,
929 "port": portNum})
930
931 }
932
933 }
934
935 }
936
937 return nil
938}
939
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530940// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530941func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530942 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000943 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530944 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
945 if err == nil {
946 if device.OperStatus == voltha.OperStatus_RECONCILING {
947 err = dh.reconcileOnus(ctx)
948 if err != nil {
949 logger.Error(ctx, "unable to reconcile onu", log.Fields{"eeror": err})
950 }
951 err = dh.reconcilePonPorts(ctx)
952 if err != nil {
953 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"eeror": err})
954 }
955 }
956 }
Girish Gowdra618fa572021-09-01 17:19:29 -0700957 // instantiate the mcast handler routines.
958 for i := range dh.incomingMcastFlowOrGroup {
959 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
960 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
961 if !dh.mcastHandlerRoutineActive[i] {
962 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
963 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
964 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
965 // for incoming mcast flow/group to be processed serially.
966 dh.mcastHandlerRoutineActive[i] = true
967 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
968 }
969 }
970
Girish Gowdru0c588b22019-04-23 23:24:56 -0400971 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400972 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400973 DeviceId: dh.device.Id,
974 OperStatus: voltha.OperStatus_ACTIVE,
975 ConnStatus: voltha.ConnectStatus_REACHABLE,
976 }); err != nil {
977 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400978 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000979
980 //Clear olt communication failure event
981 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
982 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700983 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000984 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
985
Girish Gowdru0c588b22019-04-23 23:24:56 -0400986 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530987}
988
989// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530990func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000991 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400992
khenaidoo106c61a2021-08-11 18:05:46 -0400993 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400994 if err != nil || device == nil {
995 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000996 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400997 }
998
999 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001000
1001 //Update the device oper state and connection status
1002 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001003 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001004 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001005 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001006
khenaidoodc2116e2021-10-19 17:33:19 -04001007 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001008 DeviceId: cloned.Id,
1009 OperStatus: cloned.OperStatus,
1010 ConnStatus: cloned.ConnectStatus,
1011 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001012 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001013 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001014
1015 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001016 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001017 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001018 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001019 }
1020 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001021 // Update onu state as down in onu adapter
1022 onuInd := oop.OnuIndication{}
1023 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001024
1025 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1026 if err != nil {
1027 return err
1028 }
1029 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001030 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001031 DeviceId: onuDevice.Id,
1032 OnuIndication: &onuInd,
1033 })
1034 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001035 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001036 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001037 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001038 "onu-indicator": onuInd,
1039 "device-type": onuDevice.Type,
1040 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -07001041 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001042 } else {
1043 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 -07001044 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001045 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001046 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001047 /* Discovered ONUs entries need to be cleared , since after OLT
1048 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301049 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001050 dh.lockDevice.Unlock()
1051
Neha Sharma96b7bf22020-06-15 10:37:32 +00001052 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001053 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301054}
1055
1056// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301057func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001058 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001059
1060 // if the connection is already available, close the previous connection (olt reboot case)
1061 if dh.clientCon != nil {
1062 if err = dh.clientCon.Close(); err != nil {
1063 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1064 } else {
1065 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1066 }
1067 }
1068
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301069 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +00001070 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001071 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1072 grpc.WithInsecure(),
1073 grpc.WithBlock(),
1074 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001075 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001076 )),
1077 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001078 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001079 )))
1080
1081 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301082 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301083 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001084 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001085 }
1086 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301087}
1088
1089// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301090func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001091 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301092 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001093 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301094}
1095
1096// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301097func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301098 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001099 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001100
1101 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001102 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301103 if err != nil || device == nil {
1104 /*TODO: needs to handle error scenarios */
1105 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1106 }
1107 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001108 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001109
1110 cloned := proto.Clone(device).(*voltha.Device)
1111 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1112 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1113 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001114
khenaidoodc2116e2021-10-19 17:33:19 -04001115 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001116 DeviceId: cloned.Id,
1117 OperStatus: cloned.OperStatus,
1118 ConnStatus: cloned.ConnectStatus,
1119 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301120 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 -04001121 }
1122
Chaitrashree G S44124192019-08-07 20:21:36 -04001123 // 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 +05301124 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001125 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301126 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001127 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001128 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1129 // all the modules initialized and ready to handle incoming ONUs.
1130
Thomas Lee S985938d2020-05-04 11:40:41 +05301131 err = dh.initializeDeviceHandlerModules(ctx)
1132 if err != nil {
1133 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 -04001134 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001135
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001136 go startHeartbeatCheck(ctx, dh)
1137
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001138 return nil
1139 }
1140
khenaidoo106c61a2021-08-11 18:05:46 -04001141 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001142 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -04001143 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001144 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001145 }
khenaidoo106c61a2021-08-11 18:05:46 -04001146 dh.populateActivePorts(ctx, ports.Items)
1147 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001148 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001149 }
1150
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001151 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301152 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 -04001153 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301154
Neha Sharma96b7bf22020-06-15 10:37:32 +00001155 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001156
1157 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001158 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001159 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001160
1161 go startHeartbeatCheck(ctx, dh)
1162
cuilin20187b2a8c32019-03-26 19:52:28 -07001163 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301164}
1165
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001166func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001167 var err error
1168 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001169
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001170 if dh.flowMgr != nil {
1171 dh.StopAllFlowRoutines(ctx)
1172 }
1173
1174 dh.CloseKVClient(ctx)
1175
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001176 if err != nil {
1177 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1178 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001179 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1180 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +00001181 // +1 is for NNI
1182 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1183 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001184 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001185 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1186 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1187 // There is only one NNI manager since multiple NNI is not supported for now
1188 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001189 // Instantiate resource manager
1190 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 -07001191 return olterrors.ErrResourceManagerInstantiating
1192 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001193 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001194 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1195 // the KV store to manage mcast group data. Provide the first instance (0th index)
1196 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1197 return olterrors.ErrGroupManagerInstantiating
1198 }
yasin saplid0566272021-12-21 09:10:30 +00001199 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001200 // Instantiate flow manager
1201 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001202 //Continue to check the rest of the ports
1203 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1204 } else {
1205 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001206 }
1207 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001208 /* TODO: Instantiate Alarm , stats , BW managers */
1209 /* Instantiating Event Manager to handle Alarms and KPIs */
1210 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1211
1212 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001213 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001214
1215 return nil
1216
1217}
1218
Neha Sharma96b7bf22020-06-15 10:37:32 +00001219func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001220 var err error
1221 var deviceInfo *oop.DeviceInfo
1222
Neha Sharma8f4e4322020-08-06 10:51:53 +00001223 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001224
1225 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001226 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001227 }
1228 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001229 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001230 }
1231
Neha Sharma96b7bf22020-06-15 10:37:32 +00001232 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001233 dh.device.Root = true
1234 dh.device.Vendor = deviceInfo.Vendor
1235 dh.device.Model = deviceInfo.Model
1236 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1237 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1238 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1239
1240 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001241 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001242 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001243 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001244 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001245 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001246 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001247 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001248 dh.device.MacAddress = genmac
1249 } else {
1250 dh.device.MacAddress = deviceInfo.DeviceId
1251 }
1252
1253 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001254 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001255 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001256 }
1257
1258 return deviceInfo, nil
1259}
1260
Neha Sharma96b7bf22020-06-15 10:37:32 +00001261func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001262 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001263
1264 defer func() {
1265 dh.lockDevice.Lock()
1266 dh.isCollectorActive = false
1267 dh.lockDevice.Unlock()
1268 }()
1269
1270 dh.lockDevice.Lock()
1271 dh.isCollectorActive = true
1272 dh.lockDevice.Unlock()
1273
Naga Manjunath7615e552019-10-11 22:35:47 +05301274 for {
1275 select {
1276 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001277 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301278 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001279 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001280
khenaidoo106c61a2021-08-11 18:05:46 -04001281 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001282 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001283 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001284 continue
1285 }
khenaidoo106c61a2021-08-11 18:05:46 -04001286 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301287 // NNI Stats
1288 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001289 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301290 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001291 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001292 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001293 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301294 }
1295 // PON Stats
1296 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001297 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301298 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1299 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001300 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001301 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301302 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001303 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001304
yasin sapli9e4c5092022-02-01 13:52:33 +00001305 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001306 if len(onuGemInfoLst) > 0 {
1307 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001308 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001309 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301310 }
1311 }
1312 }
1313}
1314
Mahir Gunyela2e68702022-12-07 00:00:42 -08001315// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301316func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001317 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001318 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301319 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301320
1321 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001322 cgClient, err := dh.coreClient.GetCoreServiceClient()
1323 if err != nil {
1324 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1325 return
1326 }
1327
1328 // Now, set the initial PM configuration for that device
1329 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001330 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301331 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301332}
1333
Mahir Gunyela2e68702022-12-07 00:00:42 -08001334// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001335func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1336 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001337 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301338 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001339 HwDesc: "open_pon",
1340 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001341 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001342 },
1343 SwitchFeatures: &of.OfpSwitchFeatures{
1344 NBuffers: 256,
1345 NTables: 2,
1346 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1347 of.OfpCapabilities_OFPC_TABLE_STATS |
1348 of.OfpCapabilities_OFPC_PORT_STATS |
1349 of.OfpCapabilities_OFPC_GROUP_STATS),
1350 },
1351 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301352}
1353
khenaidoo106c61a2021-08-11 18:05:46 -04001354// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001355func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001356 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001357 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001358 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001359 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001360 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1361 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()
1362 }
khenaidoo106c61a2021-08-11 18:05:46 -04001363 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Mahir Gunyela2e68702022-12-07 00:00:42 -08001364
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001365}
1366
Neha Sharma96b7bf22020-06-15 10:37:32 +00001367func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001368 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 -07001369 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370 var deviceID string
1371 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001372 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001373
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001374 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001375 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001376 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 -07001377 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1378 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001379
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001380 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301381
1382 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1383
Neha Sharma96b7bf22020-06-15 10:37:32 +00001384 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 -07001385 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001386
khenaidoodc2116e2021-10-19 17:33:19 -04001387 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001388 ParentId: dh.device.Id,
1389 OnuId: omciInd.OnuId,
1390 ParentPortNo: ponPort,
1391 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001392 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301393 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001394 "intf-id": omciInd.IntfId,
1395 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001396 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001397 deviceType = onuDevice.Type
1398 deviceID = onuDevice.Id
1399 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001400 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001402 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001403 } else {
1404 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001405 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 +05301406 deviceType = onuInCache.(*OnuDevice).deviceType
1407 deviceID = onuInCache.(*OnuDevice).deviceID
1408 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001409 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001410 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001411
khenaidoodc2116e2021-10-19 17:33:19 -04001412 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001413 ParentDeviceId: proxyDeviceID,
1414 ChildDeviceId: deviceID,
1415 Message: omciInd.Pkt,
1416 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301417 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001418 "source": dh.openOLT.config.AdapterEndpoint,
1419 "device-type": deviceType,
1420 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001421 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001422 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001423 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001424 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301425}
1426
khenaidoo106c61a2021-08-11 18:05:46 -04001427// //ProcessInterAdapterMessage sends the proxied messages to the target device
1428// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1429// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001430// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001431// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001432// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001433// return dh.handleInterAdapterOmciMsg(ctx, msg)
1434// }
1435// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1436// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001437
kesavandb9f54fd2021-11-25 20:08:04 +05301438// ProxyOmciRequests sends the proxied OMCI message to the target device
1439func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301440 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1441 return status.Error(codes.Unavailable, "OLT unreachable")
1442 }
kesavandb9f54fd2021-11-25 20:08:04 +05301443 if omciMsgs.GetProxyAddress() == nil {
1444 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1445 if err != nil {
1446 return olterrors.NewErrNotFound("onu", log.Fields{
1447 "parent-device-id": dh.device.Id,
1448 "child-device-id": omciMsgs.ChildDeviceId}, err)
1449 }
1450 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1451 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1452 return olterrors.NewErrCommunication("send-failed", log.Fields{
1453 "parent-device-id": dh.device.Id,
1454 "child-device-id": omciMsgs.ChildDeviceId}, err)
1455 }
1456 } else {
1457 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1458 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1459 return olterrors.NewErrCommunication("send-failed", log.Fields{
1460 "parent-device-id": dh.device.Id,
1461 "child-device-id": omciMsgs.ChildDeviceId}, err)
1462 }
1463 }
1464 return nil
1465}
1466
1467func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1468 var intfID uint32
1469 var onuID uint32
1470 var connectStatus common.ConnectStatus_Types
1471 if onuDevice != nil {
1472 intfID = onuDevice.ProxyAddress.GetChannelId()
1473 onuID = onuDevice.ProxyAddress.GetOnuId()
1474 connectStatus = onuDevice.ConnectStatus
1475 } else {
1476 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1477 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1478 connectStatus = omciMsgs.GetConnectStatus()
1479 }
1480 if connectStatus != voltha.ConnectStatus_REACHABLE {
1481 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1482
1483 return olterrors.NewErrCommunication("unreachable", log.Fields{
1484 "intf-id": intfID,
1485 "onu-id": onuID}, nil)
1486 }
1487
1488 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1489 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1490
1491 onuSecOmciMsgList := omciMsgs.GetMessages()
1492
1493 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1494
1495 var omciMessage *oop.OmciMsg
1496 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1497 hex.Encode(hexPkt, onuSecOmciMsg)
1498 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1499
1500 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1501 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1502 //https://jira.opencord.org/browse/VOL-4604
1503 transid := extractOmciTransactionID(onuSecOmciMsg)
1504 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1505 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1506
1507 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1508 if err != nil {
1509 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1510 "intf-id": intfID,
1511 "onu-id": onuID,
1512 "message": omciMessage}, err)
1513 }
1514 }
1515 return nil
1516}
1517
khenaidoo106c61a2021-08-11 18:05:46 -04001518// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001519func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001520 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 -07001521
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301522 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1523 return status.Error(codes.Unavailable, "OLT unreachable")
1524 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001525 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001526 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001527 if err != nil {
1528 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001529 "parent-device-id": dh.device.Id,
1530 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001531 }
khenaidoo106c61a2021-08-11 18:05:46 -04001532 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1533 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001534 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001535 "parent-device-id": dh.device.Id,
1536 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001537 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001538 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001539 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1540 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001541 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001542 "parent-device-id": dh.device.Id,
1543 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001544 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001545 }
1546 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301547}
1548
khenaidoodc2116e2021-10-19 17:33:19 -04001549func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001550 var intfID uint32
1551 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001552 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001553 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001554 intfID = onuDevice.ProxyAddress.GetChannelId()
1555 onuID = onuDevice.ProxyAddress.GetOnuId()
1556 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001557 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001558 intfID = omciMsg.GetProxyAddress().GetChannelId()
1559 onuID = omciMsg.GetProxyAddress().GetOnuId()
1560 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001561 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001562 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001563 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 -08001564
Thomas Lee S94109f12020-03-03 16:39:29 +05301565 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001566 "intf-id": intfID,
1567 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001568 }
1569
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001570 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1571 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301572 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001573 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001574 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1575 hex.Encode(hexPkt, omciMsg.Message)
1576 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1577
1578 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1579 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1580 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001581 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001582 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001583
Neha Sharma8f4e4322020-08-06 10:51:53 +00001584 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001585 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301586 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001587 "intf-id": intfID,
1588 "onu-id": onuID,
1589 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001590 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001591 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001592}
1593
David K. Bainbridge794735f2020-02-11 21:01:37 -08001594func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301595 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 +00001596 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001597 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001598 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001599 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301600 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301601 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001602 st, _ := status.FromError(err)
1603 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001604 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1605
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001606 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301607 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001608 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001609 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001610 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001611 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001612 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001613}
1614
Mahir Gunyela2e68702022-12-07 00:00:42 -08001615// getChildDevice function can be used in general to get child device, if not found in cache the function will
1616// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301617func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1618 var InCacheOnuDev *OnuDevice
1619 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1620 if onuInCache.(*OnuDevice).serialNumber == sn {
1621 InCacheOnuDev = onuInCache.(*OnuDevice)
1622 return false
1623 }
1624 return true
1625 })
1626 //Got the onu device from cache return
1627 if InCacheOnuDev != nil {
1628 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1629 return InCacheOnuDev
1630 }
1631 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1632 ParentId: dh.device.Id,
1633 SerialNumber: sn,
1634 ParentPortNo: parentPortNo,
1635 })
1636 //No device found in core return nil
1637 if onuDevice == nil {
1638 return nil
1639 }
1640 onuID := onuDevice.ProxyAddress.OnuId
1641 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1642 onuKey := dh.formOnuKey(intfID, onuID)
1643
1644 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1645 dh.onus.Store(onuKey, onuDev)
1646 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1647 return onuDev
1648}
1649
1650func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001651 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001652 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301653 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001654
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301655 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1656 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1657 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1658 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1659 if onuDev != nil {
1660 var onuGemInfo *rsrcMgr.OnuGemInfo
1661 var err error
1662 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1663 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1664 return false, err
1665 }
1666 if onuGemInfo != nil {
1667 for _, uni := range onuGemInfo.UniPorts {
1668 uniID := plt.UniIDFromPortNum(uni)
1669 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1670 if len(tpIDs) != 0 {
1671 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1672 tpInstExists = true
1673 break
1674 }
1675 }
1676 }
1677 }
1678 return tpInstExists, nil
1679 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301680
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301681 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1682 ParentId: dh.device.Id,
1683 SerialNumber: sn,
1684 ParentPortNo: parentPortNo,
1685 })
1686 if onuDevice != nil {
1687 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1688 return true, nil
1689 }
1690 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1691
1692 return false, nil
1693
1694}
1695
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001696// processDiscONULOSClear clears the LOS Alarm if it's needed
1697func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301698 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001699 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301700
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001701 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1702 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1703 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1704 OnuLosRaise event sent for it */
1705 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1706 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1707 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1708 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1709 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1710 "currentIntfId": onuDiscInd.GetIntfId()})
1711 // TODO:: Should we need to ignore raising OnuLosClear event
1712 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301713 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001714 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1715 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1716 alarmInd.LosStatus = statusCheckOff
1717 go func() {
1718 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1719 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1720 }
1721 }()
1722 // stop iterating
1723 return false
1724 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301725 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001726 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301727}
1728
1729func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301730 var error error
1731
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301732 channelID := onuDiscInd.GetIntfId()
1733 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1734
1735 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301736 defer func() {
1737 if error != nil {
1738 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1739 } else {
1740 // once the function completes set the value to false so that
1741 // we know the processing has inProcess.
1742 // Note that this is done after checking if we are already processing
1743 // to avoid changing the value from a different thread
1744 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1745 dh.discOnus.Store(sn, false)
1746 }
1747 }()
1748
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301749 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1750
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301751 tpInstExists, error := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1752 if error != nil {
1753 return error
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301754 }
1755 if tpInstExists {
1756 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001757 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001758 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001759 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001760 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1761
1762 // if the ONU existed, handle the LOS Alarm
1763 if existing {
1764
1765 if inProcess.(bool) {
1766 // if we're currently processing the ONU on a different thread, do nothing
1767 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1768 return nil
1769 }
1770 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1771 // then continue processing it
1772 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1773
1774 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001775 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301776 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001777 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001778
1779 // check the ONU is already know to the OLT
1780 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301781 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001782 ParentId: dh.device.Id,
1783 SerialNumber: sn,
1784 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001785
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301786 if error != nil {
1787 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1788 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001789 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 -08001790 switch e.Code() {
1791 case codes.Internal:
1792 // this probably means NOT FOUND, so just create a new device
1793 onuDevice = nil
1794 case codes.DeadlineExceeded:
1795 // if the call times out, cleanup and exit
1796 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301797 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1798 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001799 }
1800 }
1801 }
1802
1803 if onuDevice == nil {
1804 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001805 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001806 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001807 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301808 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001809
Neha Sharma96b7bf22020-06-15 10:37:32 +00001810 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001811
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301812 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001813 // if we can't create an ID in resource manager,
1814 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001815 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301816
1817 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001818 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301819 "serial-number": sn}, error)
1820 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001821 }
1822
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301823 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001824 ParentId: dh.device.Id,
1825 ParentPortNo: parentPortNo,
1826 ChannelId: channelID,
1827 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1828 SerialNumber: sn,
1829 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301830 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001831 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001832 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 +05301833
1834 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001835 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301836 "serial-number": sn}, error)
1837 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001838 }
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301839 if error := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); error != nil {
1840 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
1841 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
1842 "onu-id": onuID,
1843 "device-id": dh.device.Id,
1844 "serial-number": sn}, error)
1845 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04001846 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001847 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301848 log.Fields{"onuDevice": onuDevice,
1849 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001850 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301851 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001852 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001853
khenaidoo106c61a2021-08-11 18:05:46 -04001854 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1855 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301856 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04001857 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301858 if error != nil {
1859
1860 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
1861 return error
khenaidoo106c61a2021-08-11 18:05:46 -04001862 }
1863
Matteo Scandolo945e4012019-12-12 14:16:11 -08001864 // we can now use the existing ONU Id
1865 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001866 //Insert the ONU into cache to use in OnuIndication.
1867 //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 +00001868 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001869 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301870 "intfId": onuDiscInd.GetIntfId(),
1871 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001872 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001873
khenaidoo106c61a2021-08-11 18:05:46 -04001874 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301875 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001876 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301877 log.Fields{"onu": onuDev,
1878 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001879
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301880 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001881 DeviceId: onuDevice.Id,
1882 ParentDeviceId: dh.device.Id,
1883 OperStatus: common.OperStatus_DISCOVERED,
1884 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301885 }); error != nil {
1886
1887 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001888 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301889 "serial-number": sn}, error)
1890 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07001891 }
khenaidoo106c61a2021-08-11 18:05:46 -04001892
Neha Sharma96b7bf22020-06-15 10:37:32 +00001893 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301894 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
1895
1896 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001897 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301898 "serial-number": sn}, error)
1899 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08001900 }
1901 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001902}
1903
Mahir Gunyelb0046752021-02-26 13:51:05 -08001904func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001905
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001906 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001907 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001908 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001909 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001910 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301911 log.Fields{"onuId": onuInd.OnuId,
1912 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301913 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001914 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001915 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301916
David K. Bainbridge794735f2020-02-11 21:01:37 -08001917 errFields := log.Fields{"device-id": dh.device.Id}
1918
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301919 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1920
Mahir Gunyele77977b2019-06-27 05:36:22 -07001921 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1922 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001923 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001924 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001925 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001926 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1927 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001928 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001929 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001930 errFields["onu-id"] = onuInd.OnuId
1931 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001932 }
khenaidoodc2116e2021-10-19 17:33:19 -04001933 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001934 ParentId: dh.device.Id,
1935 SerialNumber: serialNumber,
1936 OnuId: onuInd.OnuId,
1937 ParentPortNo: ponPort,
1938 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001939 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001940
David K. Bainbridge794735f2020-02-11 21:01:37 -08001941 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001942 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001943 }
1944
David K. Bainbridge794735f2020-02-11 21:01:37 -08001945 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001946 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001947 "previousIntfId": onuDevice.ParentPortNo,
1948 "currentIntfId": ponPort})
1949 }
1950
1951 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001952 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301953 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1954 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301955 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001956 }
1957 if !foundInCache {
1958 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1959
khenaidoo106c61a2021-08-11 18:05:46 -04001960 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 -08001961
1962 }
kesavand7cf3a052020-08-28 12:49:18 +05301963 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001964 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001965 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301966 }
1967 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001968 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001969 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001970 }
1971 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001972}
1973
Neha Sharma96b7bf22020-06-15 10:37:32 +00001974func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001975 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 -07001976 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1977 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1978 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1979 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001980 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001981 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1982 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001983 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001984 onuInd.OperState = "down"
1985 }
1986 }
1987
David K. Bainbridge794735f2020-02-11 21:01:37 -08001988 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001989 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001990 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 -04001991
khenaidoodc2116e2021-10-19 17:33:19 -04001992 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001993 DeviceId: onuDevice.Id,
1994 OnuIndication: onuInd,
1995 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001996 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301997 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001998 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001999 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002000 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002001 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002002 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002003 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002004 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002005 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002006 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002007}
2008
cuilin20187b2a8c32019-03-26 19:52:28 -07002009func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2010 if serialNum != nil {
2011 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002012 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002013 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002014}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002015func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2016 decodedStr, err := hex.DecodeString(serialNum[4:])
2017 if err != nil {
2018 return nil, err
2019 }
2020 return &oop.SerialNumber{
2021 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002022 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002023 }, nil
2024}
cuilin20187b2a8c32019-03-26 19:52:28 -07002025
2026func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002027 if len(vendorSpecific) > 3 {
2028 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2029 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2030 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2031 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2032 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2033 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2034 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2035 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2036 return tmp
2037 }
2038 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002039}
2040
Mahir Gunyela2e68702022-12-07 00:00:42 -08002041// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002042func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302043 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002044}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002045
Mahir Gunyela2e68702022-12-07 00:00:42 -08002046// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002047func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2048 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302049 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002050 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302051 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002052
khenaidoodc2116e2021-10-19 17:33:19 -04002053 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002054 ParentId: dh.device.Id,
2055 OnuId: onuID,
2056 ParentPortNo: parentPort,
2057 })
2058
Girish Gowdru0c588b22019-04-23 23:24:56 -04002059 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002060 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002061 "intf-id": parentPort,
2062 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002063 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002064 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 -08002065 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302066}
2067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002068// SendPacketInToCore sends packet-in to core
2069// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2070// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002071func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002072 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002073 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002074 "port": logicalPort,
2075 "packet": hex.EncodeToString(packetPayload),
2076 "device-id": dh.device.Id,
2077 })
2078 }
khenaidoo106c61a2021-08-11 18:05:46 -04002079
khenaidoodc2116e2021-10-19 17:33:19 -04002080 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002081 DeviceId: dh.device.Id,
2082 Port: logicalPort,
2083 Packet: packetPayload,
2084 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302085 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002086 "source": "adapter",
2087 "destination": "core",
2088 "device-id": dh.device.Id,
2089 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002090 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002091 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002092 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002093 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002094 "packet": hex.EncodeToString(packetPayload),
2095 "device-id": dh.device.Id,
2096 })
2097 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002098 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002099}
2100
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002101// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002102func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002103 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002104
2105 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2106 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002107 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002108 }
2109
Kent Hagermane6ff1012020-07-14 15:07:53 -04002110 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002111 metrics := dh.metrics.GetSubscriberMetrics()
2112 for _, m := range pmConfigs.Metrics {
2113 metrics[m.Name].Enabled = m.Enabled
2114
2115 }
2116 }
2117}
2118
khenaidoodc2116e2021-10-19 17:33:19 -04002119func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002120 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002121 var errorsList []error
2122
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002123 if dh.getDeviceDeletionInProgressFlag() {
2124 // The device itself is going to be reset as part of deletion. So nothing to be done.
2125 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2126 return nil
2127 }
2128
Girish Gowdru0c588b22019-04-23 23:24:56 -04002129 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002130 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00002131 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002132
Neha Sharma96b7bf22020-06-15 10:37:32 +00002133 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302134 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002135 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302136 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002137 if flow_utils.HasGroup(flow) {
2138 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2139 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002140 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2141 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2142 } else {
2143 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2144 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002145 }
Girish Gowdracefae192020-03-19 18:14:10 -07002146 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002147 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
2148 //The flow we want to remove is not there, there is no need to throw an error
2149 logger.Warnw(ctx, "flow-to-remove-not-found",
2150 log.Fields{
2151 "ponIf": intfID,
2152 "flowToRemove": flow,
2153 "error": err,
2154 })
2155 } else {
2156 errorsList = append(errorsList, err)
2157 }
Girish Gowdracefae192020-03-19 18:14:10 -07002158 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002159 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302160
2161 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00002162 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002163 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302164 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002165 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302166 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002167 if flow_utils.HasGroup(flow) {
2168 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2169 } else {
yasin saplid0566272021-12-21 09:10:30 +00002170 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002171 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2172 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2173 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2174 } else {
yasin saplid0566272021-12-21 09:10:30 +00002175 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002176 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002177 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002178 if err != nil {
2179 errorsList = append(errorsList, err)
2180 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302181 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002182 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002183
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002184 return errorsList
2185}
2186
2187func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2188 var err error
2189 var errorsList []error
2190
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002191 if dh.getDeviceDeletionInProgressFlag() {
2192 // The device itself is going to be reset as part of deletion. So nothing to be done.
2193 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2194 return nil
2195 }
2196
Girish Gowdracefae192020-03-19 18:14:10 -07002197 // 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 +00002198 if groups != nil {
2199 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002200 // err = dh.groupMgr.AddGroup(ctx, group)
2201 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002202 if err != nil {
2203 errorsList = append(errorsList, err)
2204 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002205 }
2206 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002207 // err = dh.groupMgr.ModifyGroup(ctx, group)
2208 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002209 if err != nil {
2210 errorsList = append(errorsList, err)
2211 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002212 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002213 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002214 // err = dh.groupMgr.DeleteGroup(ctx, group)
2215 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002216 if err != nil {
2217 errorsList = append(errorsList, err)
2218 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002219 }
2220 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002221
2222 return errorsList
2223}
2224
Mahir Gunyela2e68702022-12-07 00:00:42 -08002225// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002226func (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 -07002227
2228 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002229
2230 if dh.getDeviceDeletionInProgressFlag() {
2231 // The device itself is going to be reset as part of deletion. So nothing to be done.
2232 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2233 return nil
2234 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302235 if dh.transitionMap.currentDeviceState != deviceStateUp {
2236 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2237 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2238 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002239 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2240 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2241 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002242 if len(errorsList) > 0 {
2243 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2244 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002245 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002246 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302247}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002248
Mahir Gunyela2e68702022-12-07 00:00:42 -08002249// DisableDevice disables the given device
2250// It marks the following for the given device:
2251// Device-Handler Admin-State : down
2252// Device Port-State: UNKNOWN
2253// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002254func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002255 /* On device disable ,admin state update has to be done prior sending request to agent since
2256 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002257 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002258 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002259 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002260 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002261 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002262 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002263 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002264 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002265 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002266 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302267
2268 dh.discOnus = sync.Map{}
2269 dh.onus = sync.Map{}
2270
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002271 dh.lockDevice.RLock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302272 //stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002273 if dh.isCollectorActive {
2274 dh.stopCollector <- true
2275 }
2276 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302277
Neha Sharma96b7bf22020-06-15 10:37:32 +00002278 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002279 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05302280 //Update device Admin state
2281 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002282
kdarapu1afeceb2020-02-12 01:38:09 -05002283 // 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 -04002284 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002285 DeviceId: cloned.Id,
2286 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2287 OperStatus: voltha.OperStatus_UNKNOWN,
2288 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002289 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002290 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002291 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002292 return nil
2293}
2294
Neha Sharma96b7bf22020-06-15 10:37:32 +00002295func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002296 // Update onu state as unreachable in onu adapter
2297 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302298 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002299
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002300 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002301 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002302 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002303 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 -04002304 }
2305 if onuDevices != nil {
2306 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002307 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002308 DeviceId: onuDevice.Id,
2309 OnuIndication: &onuInd,
2310 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002311 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002312 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002313 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002314 }
2315
2316 }
2317 }
2318
2319}
2320
Mahir Gunyela2e68702022-12-07 00:00:42 -08002321// ReenableDevice re-enables the olt device after disable
2322// It marks the following for the given device:
2323// Device-Handler Admin-State : up
2324// Device Port-State: ACTIVE
2325// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002326func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302327 if dh.Client != nil {
2328 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2329 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2330 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2331 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302332 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302333 } else {
2334 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2335
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302336 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302337
Neha Sharma96b7bf22020-06-15 10:37:32 +00002338 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002339
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002340 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002341 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002342 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002343 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002344 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2345 } else {
2346 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2347 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2348 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002349 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002350 if retError == nil {
2351 //Update the device oper status as ACTIVE
2352 device.OperStatus = voltha.OperStatus_ACTIVE
2353 } else {
2354 //Update the device oper status as FAILED
2355 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002356 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002357 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002358
khenaidoodc2116e2021-10-19 17:33:19 -04002359 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002360 DeviceId: device.Id,
2361 OperStatus: device.OperStatus,
2362 ConnStatus: device.ConnectStatus,
2363 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302364 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002365 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002366 "connect-status": device.ConnectStatus,
2367 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002368 }
kesavand39e0aa32020-01-28 20:58:50 -05002369
Neha Sharma96b7bf22020-06-15 10:37:32 +00002370 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002371
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002372 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002373}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002374
npujarec5762e2020-01-01 14:08:48 +05302375func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002376 var uniID uint32
2377 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002378 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302379 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002380 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002381 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002382 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002383 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2384 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2385 } else {
2386 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2387 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002388 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002389 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002390 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002392 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002393 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002394 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002395 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002396 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002397 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002398 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002399 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002400 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002401 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002402 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002403 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302404 }
yasin saplibddc2d72022-02-08 13:10:17 +00002405 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2406 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002407 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002408 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302409 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002410 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002411 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002412 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 -03002413 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002414 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002415 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002416 if len(errs) > 0 {
2417 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2418 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2419 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002420 return nil
2421}
2422
Devmalya Paul495b94a2019-08-27 19:42:00 -04002423// 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 +05302424func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002425 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002426 /* Clear the KV store data associated with the all the UNI ports
2427 This clears up flow data and also resource map data for various
2428 other pon resources like alloc_id and gemport_id
2429 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002430
2431 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002432
2433 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002434
Gustavo Silva41af9122022-10-11 11:05:13 -03002435 err := dh.cleanupDeviceResources(ctx)
2436 if err != nil {
2437 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2438 } else {
2439 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2440 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002441
Himani Chawla49a5d562020-11-25 11:53:44 +05302442 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002443 // Stop the Stats collector
2444 if dh.isCollectorActive {
2445 dh.stopCollector <- true
2446 }
2447 // stop the heartbeat check routine
2448 if dh.isHeartbeatCheckActive {
2449 dh.stopHeartbeatCheck <- true
2450 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302451 // Stop the read indication only if it the routine is active
2452 if dh.isReadIndicationRoutineActive {
2453 dh.stopIndications <- true
2454 }
2455 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002456 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002457 //Reset the state
2458 if dh.Client != nil {
2459 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002460 go func() {
2461 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
2462 if err = dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err != nil {
2463 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
2464 }
2465 }()
2466 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002467 }
2468 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002469 // There is no need to update the core about operation status and connection status of the OLT.
2470 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2471 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2472 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002473
khenaidoo7eb2d672021-10-22 19:08:50 -04002474 // Stop the adapter grpc clients for that parent device
2475 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002476 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002477}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002478
2479// StopAllFlowRoutines stops all flow routines
2480func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2481 var wg sync.WaitGroup
2482 wg.Add(1) // for the mcast routine below to finish
2483 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2484 for _, flMgr := range dh.flowMgr {
2485 if flMgr != nil {
2486 wg.Add(1) // for the flow handler routine below to finish
2487 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2488 }
2489 }
2490 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2491 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2492 } else {
2493 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2494 }
2495}
2496
Gustavo Silva41af9122022-10-11 11:05:13 -03002497func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2498 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002499 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302500 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002501 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002502 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002503 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002504 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002505 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2506 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302507 }
2508 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002509 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2510 errs = append(errs, err)
2511 }
2512 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2513 errs = append(errs, err)
2514 }
2515 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2516 errs = append(errs, err)
2517 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002518 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002519 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002520 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002521 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002522 }
2523 // Clean up NNI manager's data
2524 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2525 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002526 }
A R Karthick1f85b802019-10-11 05:06:05 +00002527
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002528 dh.CloseKVClient(ctx)
2529
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002530 // Take one final sweep at cleaning up KV store for the OLT device
2531 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002532 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2533 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002534 }
2535
Devmalya Paul495b94a2019-08-27 19:42:00 -04002536 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302537 dh.onus.Range(func(key interface{}, value interface{}) bool {
2538 dh.onus.Delete(key)
2539 return true
2540 })
2541
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002542 /*Delete discovered ONU map for the device*/
2543 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2544 dh.discOnus.Delete(key)
2545 return true
2546 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002547 if len(errs) > 0 {
2548 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2549 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2550 }
2551 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002552}
2553
Mahir Gunyela2e68702022-12-07 00:00:42 -08002554// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002555func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302556 if dh.Client != nil {
2557 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2558 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2559 }
2560 } else {
2561 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2562
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002563 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302564
Neha Sharma96b7bf22020-06-15 10:37:32 +00002565 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002566 return nil
2567}
2568
David K. Bainbridge794735f2020-02-11 21:01:37 -08002569func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002570 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002571 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002572 "packet-indication": *packetIn,
2573 "device-id": dh.device.Id,
2574 "packet": hex.EncodeToString(packetIn.Pkt),
2575 })
2576 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002577 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2578 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2579 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002580 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002581 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002582 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002583 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002584 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002585 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002586 "logical-port-num": logicalPortNum,
2587 "device-id": dh.device.Id,
2588 "packet": hex.EncodeToString(packetIn.Pkt),
2589 })
2590 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002591
khenaidoodc2116e2021-10-19 17:33:19 -04002592 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002593 DeviceId: dh.device.Id,
2594 Port: logicalPortNum,
2595 Packet: packetIn.Pkt,
2596 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302597 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002598 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302599 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002600 "device-id": dh.device.Id,
2601 "packet": hex.EncodeToString(packetIn.Pkt),
2602 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002603 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002604
Matteo Scandolo92186242020-06-12 10:54:18 -07002605 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002606 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002607 "packet": hex.EncodeToString(packetIn.Pkt),
2608 "device-id": dh.device.Id,
2609 })
2610 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002611 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002612}
2613
Mahir Gunyela2e68702022-12-07 00:00:42 -08002614// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2615func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2616 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2617 if err != nil {
2618 return olterrors.NewErrInvalidValue(log.Fields{
2619 "egress-nni-port": egressPortNo,
2620 "device-id": dh.device.Id,
2621 }, err)
2622 }
2623 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2624
2625 if logger.V(log.DebugLevel) {
2626 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2627 "uplink-pkt": uplinkPkt,
2628 "packet": hex.EncodeToString(packet.Data),
2629 "device-id": dh.device.Id,
2630 })
2631 }
2632
2633 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2634 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2635 "packet": hex.EncodeToString(packet.Data),
2636 "device-id": dh.device.Id,
2637 }, err)
2638 }
2639 return nil
2640}
2641
2642// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2643func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2644 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2645 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2646 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2647 // Do not packet-out lldp packets on uni port.
2648 // ONOS has no clue about uni/nni ports, it just packets out on all
2649 // available ports on the Logical Switch. It should not be interested
2650 // in the UNI links.
2651 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2652 "device-id": dh.device.Id,
2653 })
2654 return nil
2655 }
2656 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2657 if innerEthType == 0x8100 {
2658 // q-in-q 802.1ad or 802.1q double tagged packet.
2659 // slice out the outer tag.
2660 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2661 if logger.V(log.DebugLevel) {
2662 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2663 "packet-data": hex.EncodeToString(packet.Data),
2664 "device-id": dh.device.Id,
2665 })
2666 }
2667 }
2668 }
2669 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2670 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2671 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2672 var gemPortID uint32
2673 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2674 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2675 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2676 }
2677 if err != nil {
2678 // In this case the openolt agent will receive the gemPortID as 0.
2679 // The agent tries to retrieve the gemPortID in this case.
2680 // This may not always succeed at the agent and packetOut may fail.
2681 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2682 "intf-id": intfID,
2683 "onu-id": onuID,
2684 "uni-id": uniID,
2685 "packet": hex.EncodeToString(packet.Data),
2686 "device-id": dh.device.Id,
2687 "error": err,
2688 })
2689 }
2690
2691 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2692 if logger.V(log.DebugLevel) {
2693 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2694 "egress-port-no": egressPortNo,
2695 "intf-id": intfID,
2696 "onu-id": onuID,
2697 "uni-id": uniID,
2698 "gem-port-id": gemPortID,
2699 "packet": hex.EncodeToString(packet.Data),
2700 "device-id": dh.device.Id,
2701 })
2702 }
2703
2704 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2705 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2706 "source": "adapter",
2707 "destination": "onu",
2708 "egress-port-number": egressPortNo,
2709 "intf-id": intfID,
2710 "oni-id": onuID,
2711 "uni-id": uniID,
2712 "gem-port-id": gemPortID,
2713 "packet": hex.EncodeToString(packet.Data),
2714 "device-id": dh.device.Id,
2715 }, err)
2716 }
2717 return nil
2718}
2719
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002720// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002721func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002722 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002723 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002724 "device-id": dh.device.Id,
2725 "egress-port-no": egressPortNo,
2726 "pkt-length": len(packet.Data),
2727 "packet": hex.EncodeToString(packet.Data),
2728 })
2729 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002730
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002731 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002732 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002733 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002734 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002735 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002736 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002737 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002738 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302739 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002740 "egressPortType": egressPortType,
2741 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302742 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002743 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002744 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002745 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002746}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002747
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002748func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2749 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002750}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302751
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002752func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002753
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002754 defer func() {
2755 dh.lockDevice.Lock()
2756 dh.isHeartbeatCheckActive = false
2757 dh.lockDevice.Unlock()
2758 }()
2759
2760 dh.lockDevice.Lock()
2761 dh.isHeartbeatCheckActive = true
2762 dh.lockDevice.Unlock()
2763
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302764 // start the heartbeat check towards the OLT.
2765 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302766 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302767
2768 for {
2769 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2770 select {
2771 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002772 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002773 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002774 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302775 if timerCheck == nil {
2776 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002777 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302778 }
2779 } else {
2780 if timerCheck != nil {
2781 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002782 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302783 }
2784 timerCheck = nil
2785 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302786 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2787 if dh.heartbeatSignature == 0 {
2788 // First time the signature will be 0, update the signture to DB when not found.
2789 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2790 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2791 }
2792 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2793
2794 dh.lockDevice.RLock()
2795 // Stop the read indication only if it the routine is active
2796 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2797 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2798 // on next execution of the readIndication routine.
2799 if !dh.isReadIndicationRoutineActive {
2800 // Start reading indications
2801 go func() {
2802 if err = dh.readIndications(ctx); err != nil {
2803 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2804 }
2805 }()
2806 }
2807 dh.lockDevice.RUnlock()
2808
2809 } else {
2810 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2811 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2812 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2813 go dh.updateStateRebooted(ctx)
2814 }
2815
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302816 }
2817 cancel()
2818 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002819 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302820 return
2821 }
2822 }
2823}
2824
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002825func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002826 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002827 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002828 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2829 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2830 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2831 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2832 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002833 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002834 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2835 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002836 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302837
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302838 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002839 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002840 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002841 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002842 DeviceId: dh.device.Id,
2843 OperStatus: voltha.OperStatus_UNKNOWN,
2844 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2845 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002846 _ = 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 -04002847 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302848 /*
2849 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2850 DeviceId: dh.device.Id,
2851 PortTypeFilter: 0,
2852 OperStatus: voltha.OperStatus_UNKNOWN,
2853 }); err != nil {
2854 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2855 }
2856 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002857
2858 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002859 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002860 cloned := proto.Clone(device).(*voltha.Device)
2861 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2862 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2863 dh.device = cloned // update local copy of the device
2864 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002865
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002866 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002867 // Stop the Stats collector
2868 if dh.isCollectorActive {
2869 dh.stopCollector <- true
2870 }
2871 // stop the heartbeat check routine
2872 if dh.isHeartbeatCheckActive {
2873 dh.stopHeartbeatCheck <- true
2874 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002875 // Stop the read indication only if it the routine is active
2876 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2877 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2878 // on next execution of the readIndication routine.
2879 if dh.isReadIndicationRoutineActive {
2880 dh.stopIndications <- true
2881 }
2882 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002883 dh.transitionMap.Handle(ctx, DeviceInit)
2884
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302885 }
2886}
kesavand39e0aa32020-01-28 20:58:50 -05002887
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302888func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2889 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2890 if err != nil || device == nil {
2891 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2892 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2893 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2894 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2895 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2896 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2897 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2898 return
2899 }
Mahir Gunyel701df862023-09-07 16:16:04 -07002900 //Starting the cleanup process
2901 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302902
2903 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2904 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2905 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2906 DeviceId: dh.device.Id,
2907 OperStatus: voltha.OperStatus_REBOOTED,
2908 ConnStatus: voltha.ConnectStatus_REACHABLE,
2909 }); err != nil {
2910 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2911 }
2912
2913 dh.lockDevice.RLock()
2914 // Stop the read indication only if it the routine is active
2915 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2916 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2917 // on next execution of the readIndication routine.
2918 if dh.isReadIndicationRoutineActive {
2919 dh.stopIndications <- true
2920 }
2921 dh.lockDevice.RUnlock()
2922
2923 //raise olt communication failure event
2924 raisedTs := time.Now().Unix()
2925 cloned := proto.Clone(device).(*voltha.Device)
2926 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2927 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2928 dh.device = cloned // update local copy of the device
2929 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2930
Gustavo Silva41af9122022-10-11 11:05:13 -03002931 if err := dh.cleanupDeviceResources(ctx); err != nil {
2932 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
2933 } else {
2934 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2935 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002936
2937 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302938 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002939 if dh.isCollectorActive {
2940 dh.stopCollector <- true
2941 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302942 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002943 if dh.isHeartbeatCheckActive {
2944 dh.stopHeartbeatCheck <- true
2945 }
2946 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302947
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002948 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302949
2950 //reset adapter reconcile flag
2951 dh.adapterPreviouslyConnected = false
2952 for {
2953
2954 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2955 if err != nil || childDevices == nil {
2956 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2957 continue
2958 }
2959 if len(childDevices.Items) == 0 {
2960 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
2961 break
2962 } else {
2963 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
2964 time.Sleep(5 * time.Second)
2965 }
2966
2967 }
Mahir Gunyel701df862023-09-07 16:16:04 -07002968 //Cleanup completed , reset the flag
2969 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302970 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
2971 dh.transitionMap.Handle(ctx, DeviceInit)
2972
2973}
2974
kesavand39e0aa32020-01-28 20:58:50 -05002975// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002976func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2977 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2978 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002979}
2980
2981// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002982func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2983 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2984 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002985}
2986
Mahir Gunyela2e68702022-12-07 00:00:42 -08002987// 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 +00002988func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2989 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002990 if port.GetType() == voltha.Port_ETHERNET_NNI {
2991 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002992 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302993 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302994 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002995 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002996 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002997 }
2998 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002999 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003000 ponIntf := &oop.Interface{IntfId: ponID}
3001 var operStatus voltha.OperStatus_Types
3002 if enablePort {
3003 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303004 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003005
3006 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303007 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003008 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003009 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003010 }
3011 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003012 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003013 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003014 } else {
3015 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303016 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003017 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303018 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003019 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003020 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003021 }
3022 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003023 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003025 }
khenaidoodc2116e2021-10-19 17:33:19 -04003026 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003027 DeviceId: dh.device.Id,
3028 PortType: voltha.Port_PON_OLT,
3029 PortNo: port.PortNo,
3030 OperStatus: operStatus,
3031 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303032 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303033 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003034 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003035 }
3036 return nil
3037}
3038
Mahir Gunyela2e68702022-12-07 00:00:42 -08003039// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003040func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003041 // Disable the port and update the oper_port_status to core
3042 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003043 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003044 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303046 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303047 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003048 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003049 }
3050 }
3051 }
3052 return nil
3053}
3054
Mahir Gunyela2e68702022-12-07 00:00:42 -08003055// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003056func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3057 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3058 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003059 if port.Type == voltha.Port_ETHERNET_NNI {
3060 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003061 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003062 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003063 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003064 }
3065 }
3066 if port.Type == voltha.Port_PON_OLT {
3067 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003068 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003069 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003070 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003071 }
3072 }
3073 }
3074}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003075
3076// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003077func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003078 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003079 if dh.getDeviceDeletionInProgressFlag() {
3080 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3081 // will reboot, so everything will be reset on the pOLT too.
3082 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3083 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3084 return nil
3085 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003086 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003087 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003088
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003089 var sn *oop.SerialNumber
3090 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003091 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303092 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003093 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303094 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003095 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003096 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003097
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003098 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003099 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003100 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003101 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3102 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3103 "device-id": dh.device.Id,
3104 "intf-id": intfID,
3105 "onuID": onuID,
3106 "err": err})
3107 } else {
3108 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003109 // Delete flows from device before schedulers and queue
3110 // Clear flowids for gem cache.
3111 removedFlows := []uint64{}
3112 for _, gem := range onuGem.GemPorts {
3113 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3114 for _, flowID := range flowIDs {
3115 //multiple gem port can have the same flow id
3116 //it is better to send only one flowRemove request to the agent
3117 var alreadyRemoved bool
3118 for _, removedFlowID := range removedFlows {
3119 if removedFlowID == flowID {
3120 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3121 alreadyRemoved = true
3122 break
3123 }
3124 }
3125 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003126 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003127 removedFlows = appendUnique64bit(removedFlows, flowID)
3128 }
3129 }
3130 }
3131 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3132 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003133 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3134 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3135 "device-id": dh.device.Id,
3136 "onu-device": onu,
3137 "err": err})
3138 }
yasin saplibddc2d72022-02-08 13:10:17 +00003139 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003140 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3141 "intf-id": intfID,
3142 "onu-device": onu,
3143 "onu-gem": onuGem,
3144 "err": err})
3145 //Not returning error on cleanup.
3146 }
3147 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05303148
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003149 }
yasin saplibddc2d72022-02-08 13:10:17 +00003150 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003151 dh.onus.Delete(onuKey)
3152 dh.discOnus.Delete(onuSn)
3153
3154 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003155 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303156 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303157 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003158 "onu-id": onuID}, err).Log()
3159 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003160
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003161 return nil
3162}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003163func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3164 flow := &oop.Flow{FlowId: flowID}
3165 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3166 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3167 "device-id": dh.device.Id})
3168 } else {
3169 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3170 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3171 "device-id": dh.device.Id,
3172 "err": err})
3173 }
3174 }
3175}
Girish Gowdracefae192020-03-19 18:14:10 -07003176
3177func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003178 for _, field := range flow_utils.GetOfbFields(flow) {
3179 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003180 return field.GetPort()
3181 }
3182 }
3183 return InvalidPort
3184}
3185
3186func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003187 for _, action := range flow_utils.GetActions(flow) {
3188 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003189 if out := action.GetOutput(); out != nil {
3190 return out.GetPort()
3191 }
3192 }
3193 }
3194 return InvalidPort
3195}
3196
Girish Gowdracefae192020-03-19 18:14:10 -07003197func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3198 inPort := getInPortFromFlow(flow)
3199 outPort := getOutPortFromFlow(flow)
3200
3201 if inPort == InvalidPort || outPort == InvalidPort {
3202 return inPort, outPort
3203 }
3204
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003205 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003206 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003207 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003208 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003209 return uniPort, outPort
3210 }
3211 }
3212 } else {
3213 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003214 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003215 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003216 return inPort, uniPort
3217 }
3218 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003219 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003220 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003221 return uniPort, outPort
3222 }
3223 }
3224 }
3225
3226 return InvalidPort, InvalidPort
3227}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003228
3229func extractOmciTransactionID(omciPkt []byte) uint16 {
3230 if len(omciPkt) > 3 {
3231 d := omciPkt[0:2]
3232 transid := binary.BigEndian.Uint16(d)
3233 return transid
3234 }
3235 return 0
3236}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003237
3238// StoreOnuDevice stores the onu parameters to the local cache.
3239func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3240 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3241 dh.onus.Store(onuKey, onuDevice)
3242}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003243
khenaidoodc2116e2021-10-19 17:33:19 -04003244func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003245 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003246 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003247 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003248 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003249 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003250 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003251 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003252 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3253 return nil, err
3254 }
3255 ID = device.ProxyAddress.GetOnuId()
3256 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3257 valueparam.Onu = &Onu
3258 valueparam.Value = value
3259
3260 // This API is unsupported until agent patch is added
3261 resp.Unsupported = uint32(value)
3262 _ = ctx
3263
3264 // Uncomment this code once agent changes are complete and tests
3265 /*
3266 resp, err = dh.Client.GetValue(ctx, valueparam)
3267 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003268 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003269 return nil, err
3270 }
3271 */
3272
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003273 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 -08003274 return resp, nil
3275}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003276
yasin saplid0566272021-12-21 09:10:30 +00003277func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
3278 // Default to NNI
3279 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003280 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003281 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003282 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003283 }
3284 return intfID
3285}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003286
Mahir Gunyelb0046752021-02-26 13:51:05 -08003287func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
3288 dh.perPonOnuIndicationChannelLock.Lock()
3289 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3290 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003291 return ch.indicationChannel
3292 }
3293 channels := onuIndicationChannels{
3294 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08003295 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003296 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003297 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003298 stopChannel: make(chan struct{}),
3299 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003300 dh.perPonOnuIndicationChannel[intfID] = channels
3301 dh.perPonOnuIndicationChannelLock.Unlock()
3302 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003303 return channels.indicationChannel
3304
3305}
3306
Mahir Gunyelb0046752021-02-26 13:51:05 -08003307func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3308 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3309 dh.perPonOnuIndicationChannelLock.Lock()
3310 defer dh.perPonOnuIndicationChannelLock.Unlock()
3311 for _, v := range dh.perPonOnuIndicationChannel {
3312 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003313 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003314 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003315}
3316
Mahir Gunyelb0046752021-02-26 13:51:05 -08003317func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3318 ind := onuIndicationMsg{
3319 ctx: ctx,
3320 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003321 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003322 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003323 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003324 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003325}
3326
Mahir Gunyelb0046752021-02-26 13:51:05 -08003327func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003328 for {
3329 select {
3330 // process one indication per onu, before proceeding to the next one
3331 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003332 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003333 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003334 "ind": indication})
3335 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003336 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003337 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003338 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3339 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003340 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003341 }
3342 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003343 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003344 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3345 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003346 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003347 }
3348 }
3349 case <-onuChannels.stopChannel:
3350 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3351 close(onuChannels.indicationChannel)
3352 return
3353 }
3354 }
3355}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003356
3357// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3358// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003359func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003360 if dh.getDeviceDeletionInProgressFlag() {
3361 // The device itself is going to be reset as part of deletion. So nothing to be done.
3362 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3363 return nil
3364 }
3365
Girish Gowdra491a9c62021-01-06 16:43:07 -08003366 // Step1 : Fill McastFlowOrGroupControlBlock
3367 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3368 // Step3 : Wait on response channel for response
3369 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003370 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003371 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3372 errChan := make(chan error)
3373 var groupID uint32
3374 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3375 ctx: ctx,
3376 flowOrGroupAction: action,
3377 flow: flow,
3378 group: group,
3379 errChan: &errChan,
3380 }
3381 if flow != nil {
3382 groupID = flow_utils.GetGroup(flow)
3383 } else if group != nil {
3384 groupID = group.Desc.GroupId
3385 } else {
3386 return errors.New("flow-and-group-both-nil")
3387 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003388 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3389 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3390 // Derive the appropriate go routine to handle the request by a simple module operation.
3391 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3392 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3393 // Wait for handler to return error value
3394 err := <-errChan
3395 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3396 return err
3397 }
3398 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3399 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003400}
3401
3402// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003403func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003404 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003405 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003406 // block on the channel to receive an incoming mcast flow/group
3407 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003408 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3409 if mcastFlowOrGroupCb.flow != nil {
3410 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3411 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3412 log.Fields{"device-id": dh.device.Id,
3413 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003414 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3415 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3416 for _, flMgr := range dh.flowMgr {
3417 if flMgr != nil {
3418 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3419 break
3420 }
3421 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003422 // Pass the return value over the return channel
3423 *mcastFlowOrGroupCb.errChan <- err
3424 } else { // flow remove
3425 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3426 log.Fields{"device-id": dh.device.Id,
3427 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003428 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3429 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3430 for _, flMgr := range dh.flowMgr {
3431 if flMgr != nil {
3432 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3433 break
3434 }
3435 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003436 // Pass the return value over the return channel
3437 *mcastFlowOrGroupCb.errChan <- err
3438 }
3439 } else { // mcast group
3440 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3441 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3442 log.Fields{"device-id": dh.device.Id,
3443 "groupToAdd": mcastFlowOrGroupCb.group})
3444 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3445 // Pass the return value over the return channel
3446 *mcastFlowOrGroupCb.errChan <- err
3447 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3448 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3449 log.Fields{"device-id": dh.device.Id,
3450 "groupToModify": mcastFlowOrGroupCb.group})
3451 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3452 // Pass the return value over the return channel
3453 *mcastFlowOrGroupCb.errChan <- err
3454 } else { // group remove
3455 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3456 log.Fields{"device-id": dh.device.Id,
3457 "groupToRemove": mcastFlowOrGroupCb.group})
3458 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3459 // Pass the return value over the return channel
3460 *mcastFlowOrGroupCb.errChan <- err
3461 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003462 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003463 case <-stopHandler:
3464 dh.mcastHandlerRoutineActive[routineIndex] = false
3465 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003466 }
3467 }
3468}
kesavand62126212021-01-12 04:56:06 -05003469
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003470// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003471func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003472 for i, v := range dh.stopMcastHandlerRoutine {
3473 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003474 select {
3475 case v <- true:
3476 case <-time.After(time.Second * 5):
3477 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3478 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003479 }
3480 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003481
3482 if dh.incomingMcastFlowOrGroup != nil {
3483 for k := range dh.incomingMcastFlowOrGroup {
3484 if dh.incomingMcastFlowOrGroup[k] != nil {
3485 dh.incomingMcastFlowOrGroup[k] = nil
3486 }
3487 }
3488 dh.incomingMcastFlowOrGroup = nil
3489 }
3490
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003491 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003492 logger.Debug(ctx, "stopped all mcast handler routines")
3493}
3494
kesavand62126212021-01-12 04:56:06 -05003495func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3496
3497 singleValResp := extension.SingleGetValueResponse{
3498 Response: &extension.GetValueResponse{
3499 Response: &extension.GetValueResponse_PortCoutners{
3500 PortCoutners: &extension.GetOltPortCountersResponse{},
3501 },
3502 },
3503 }
3504
3505 errResp := func(status extension.GetValueResponse_Status,
3506 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3507 return &extension.SingleGetValueResponse{
3508 Response: &extension.GetValueResponse{
3509 Status: status,
3510 ErrReason: reason,
3511 },
3512 }
3513 }
3514
3515 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3516 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3517 //send error response
3518 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3519 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3520 }
3521 statIndChn := make(chan bool, 1)
3522 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3523 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3524 //request openOlt agent to send the the port statistics indication
3525
3526 go func() {
3527 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3528 if err != nil {
3529 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3530 }
3531 }()
3532 select {
3533 case <-statIndChn:
3534 //indication received for ports stats
3535 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3536 case <-time.After(oltPortInfoTimeout * time.Second):
3537 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3538 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3539 case <-ctx.Done():
3540 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3541 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3542 }
3543 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3544 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003545 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003546 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3547 cmnni := dh.portStats.collectNNIMetrics(intfID)
3548 if cmnni == nil {
3549 //TODO define the error reason
3550 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3551 }
3552 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3553 return &singleValResp
3554
3555 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3556 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003557 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003558 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3559 cmpon := dh.portStats.collectPONMetrics(intfID)
3560 if cmpon == nil {
3561 //TODO define the error reason
3562 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3563 }
3564 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3565 return &singleValResp
3566 }
3567 }
3568 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3569}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303570
3571func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3572
3573 singleValResp := extension.SingleGetValueResponse{
3574 Response: &extension.GetValueResponse{
3575 Response: &extension.GetValueResponse_OnuPonCounters{
3576 OnuPonCounters: &extension.GetOnuCountersResponse{},
3577 },
3578 },
3579 }
3580
3581 errResp := func(status extension.GetValueResponse_Status,
3582 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3583 return &extension.SingleGetValueResponse{
3584 Response: &extension.GetValueResponse{
3585 Status: status,
3586 ErrReason: reason,
3587 },
3588 }
3589 }
3590 intfID := onuPonInfo.IntfId
3591 onuID := onuPonInfo.OnuId
3592 onuKey := dh.formOnuKey(intfID, onuID)
3593
3594 if _, ok := dh.onus.Load(onuKey); !ok {
3595 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3596 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3597 }
3598 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3599 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3600 if cmnni == nil {
3601 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3602 }
3603 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3604 return &singleValResp
3605
3606}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003607
nikesh.krishnanc8473432023-06-14 12:14:54 +05303608func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
3609
3610 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3611 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3612 if err != nil {
3613 return nil, err
3614 }
3615 return OnuInfo, nil
3616
3617}
3618
3619func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
3620
3621 Intf := oop.Interface{IntfId: intfID}
3622 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3623 if err != nil {
3624 return nil, err
3625 }
3626 return IntfInfo, nil
3627
3628}
3629
Gamze Abaka85e9a142021-05-26 13:41:39 +00003630func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3631
3632 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3633 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3634 if err != nil {
3635 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3636 return generateSingleGetValueErrorResponse(err)
3637 }
3638 return &extension.SingleGetValueResponse{
3639 Response: &extension.GetValueResponse{
3640 Status: extension.GetValueResponse_OK,
3641 Response: &extension.GetValueResponse_RxPower{
3642 RxPower: &extension.GetRxPowerResponse{
3643 IntfId: rxPowerRequest.IntfId,
3644 OnuId: rxPowerRequest.OnuId,
3645 Status: rxPower.Status,
3646 FailReason: rxPower.FailReason.String(),
3647 RxPower: rxPower.RxPowerMeanDbm,
3648 },
3649 },
3650 },
3651 }
3652}
3653
praneeth nalmas55616d62023-02-06 09:19:18 +05303654func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
3655
3656 errResp := func(status extension.GetValueResponse_Status,
3657 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3658 return &extension.SingleGetValueResponse{
3659 Response: &extension.GetValueResponse{
3660 Status: status,
3661 ErrReason: reason,
3662 },
3663 }
3664 }
3665
3666 resp := extension.SingleGetValueResponse{
3667 Response: &extension.GetValueResponse{
3668 Status: extension.GetValueResponse_OK,
3669 Response: &extension.GetValueResponse_OltRxPower{
3670 OltRxPower: &extension.GetOltRxPowerResponse{},
3671 },
3672 },
3673 }
3674
3675 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3676 portLabel := OltRxPowerRequest.PortLabel
3677 serialNumber := OltRxPowerRequest.OnuSn
3678
3679 portInfo := strings.Split(portLabel, "-")
3680 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3681
3682 if err != nil {
3683 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3684 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3685 }
3686
3687 if portInfo[0] != "pon" {
3688 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3689 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3690 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303691
3692 if serialNumber != "" {
3693
3694 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3695 if onuDev != nil {
3696
3697 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3698 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3699 if err != nil {
3700
3701 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3702 return generateSingleGetValueErrorResponse(err)
3703
3704 }
3705
3706 rxPowerValue := extension.RxPower{}
3707 rxPowerValue.OnuSn = onuDev.serialNumber
3708 rxPowerValue.Status = rxPower.GetStatus()
3709 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3710 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3711
3712 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3713
3714 } else {
3715
3716 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3717 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3718 }
3719
3720 } else {
3721
3722 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303723 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth nalmas55616d62023-02-06 09:19:18 +05303724
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303725 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05303726 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3727 if err != nil {
3728 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3729 } else {
3730
3731 rxPowerValue := extension.RxPower{}
3732 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3733 rxPowerValue.Status = rxPower.GetStatus()
3734 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3735 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3736
3737 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3738 }
3739
3740 }
3741 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3742 return true
3743 })
3744 }
3745 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3746 return &resp
3747}
3748
Gamze Abaka85e9a142021-05-26 13:41:39 +00003749func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3750 errResp := func(status extension.GetValueResponse_Status,
3751 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3752 return &extension.SingleGetValueResponse{
3753 Response: &extension.GetValueResponse{
3754 Status: status,
3755 ErrReason: reason,
3756 },
3757 }
3758 }
3759
3760 if err != nil {
3761 if e, ok := status.FromError(err); ok {
3762 switch e.Code() {
3763 case codes.Internal:
3764 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3765 case codes.DeadlineExceeded:
3766 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3767 case codes.Unimplemented:
3768 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3769 case codes.NotFound:
3770 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3771 }
3772 }
3773 }
3774
3775 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3776}
khenaidoo106c61a2021-08-11 18:05:46 -04003777
3778/*
3779Helper functions to communicate with Core
3780*/
3781
3782func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3783 cClient, err := dh.coreClient.GetCoreServiceClient()
3784 if err != nil || cClient == nil {
3785 return nil, err
3786 }
3787 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3788 defer cancel()
3789 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3790}
3791
khenaidoodc2116e2021-10-19 17:33:19 -04003792func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003793 cClient, err := dh.coreClient.GetCoreServiceClient()
3794 if err != nil || cClient == nil {
3795 return nil, err
3796 }
3797 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3798 defer cancel()
3799 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3800}
3801
khenaidoodc2116e2021-10-19 17:33:19 -04003802func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003803 cClient, err := dh.coreClient.GetCoreServiceClient()
3804 if err != nil || cClient == nil {
3805 return err
3806 }
3807 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3808 defer cancel()
3809 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3810 return err
3811}
3812
3813func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3814 cClient, err := dh.coreClient.GetCoreServiceClient()
3815 if err != nil || cClient == nil {
3816 return nil, err
3817 }
3818 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3819 defer cancel()
3820 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3821}
3822
3823func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3824 cClient, err := dh.coreClient.GetCoreServiceClient()
3825 if err != nil || cClient == nil {
3826 return nil, err
3827 }
3828 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3829 defer cancel()
3830 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3831}
3832
3833func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3834 cClient, err := dh.coreClient.GetCoreServiceClient()
3835 if err != nil || cClient == nil {
3836 return err
3837 }
3838 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3839 defer cancel()
3840 _, err = cClient.DeviceUpdate(subCtx, device)
3841 return err
3842}
3843
khenaidoodc2116e2021-10-19 17:33:19 -04003844func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003845 cClient, err := dh.coreClient.GetCoreServiceClient()
3846 if err != nil || cClient == nil {
3847 return nil, err
3848 }
3849 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3850 defer cancel()
3851 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3852}
3853
khenaidoodc2116e2021-10-19 17:33:19 -04003854func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003855 cClient, err := dh.coreClient.GetCoreServiceClient()
3856 if err != nil || cClient == nil {
3857 return err
3858 }
3859 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3860 defer cancel()
3861 _, err = cClient.SendPacketIn(subCtx, pkt)
3862 return err
3863}
3864
3865func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3866 cClient, err := dh.coreClient.GetCoreServiceClient()
3867 if err != nil || cClient == nil {
3868 return err
3869 }
3870 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3871 defer cancel()
3872 _, err = cClient.PortCreated(subCtx, port)
3873 return err
3874}
3875
khenaidoodc2116e2021-10-19 17:33:19 -04003876func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003877 cClient, err := dh.coreClient.GetCoreServiceClient()
3878 if err != nil || cClient == nil {
3879 return err
3880 }
3881 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3882 defer cancel()
3883 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3884 return err
3885}
3886
khenaidoodc2116e2021-10-19 17:33:19 -04003887func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003888 cClient, err := dh.coreClient.GetCoreServiceClient()
3889 if err != nil || cClient == nil {
3890 return err
3891 }
3892 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3893 defer cancel()
3894 _, err = cClient.PortStateUpdate(subCtx, portState)
3895 return err
3896}
3897
khenaidoodc2116e2021-10-19 17:33:19 -04003898func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003899 cClient, err := dh.coreClient.GetCoreServiceClient()
3900 if err != nil || cClient == nil {
3901 return nil, err
3902 }
3903 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3904 defer cancel()
3905 return cClient.GetDevicePort(subCtx, portFilter)
3906}
3907
nikesh.krishnanc8473432023-06-14 12:14:54 +05303908func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
3909 cClient, err := dh.coreClient.GetCoreServiceClient()
3910 if err != nil || cClient == nil {
3911 return nil, err
3912 }
3913 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3914 defer cancel()
3915 return cClient.GetPorts(subCtx, portFilter)
3916}
3917
khenaidoo106c61a2021-08-11 18:05:46 -04003918/*
3919Helper functions to communicate with child adapter
3920*/
3921
khenaidoodc2116e2021-10-19 17:33:19 -04003922func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003923 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3924 if err != nil || aClient == nil {
3925 return err
3926 }
3927 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3928 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3929 defer cancel()
3930 _, err = aClient.OmciIndication(subCtx, response)
3931 return err
3932}
3933
khenaidoodc2116e2021-10-19 17:33:19 -04003934func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003935 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3936 if err != nil || aClient == nil {
3937 return err
3938 }
3939 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3940 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3941 defer cancel()
3942 _, err = aClient.OnuIndication(subCtx, onuInd)
3943 return err
3944}
3945
khenaidoodc2116e2021-10-19 17:33:19 -04003946func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003947 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3948 if err != nil || aClient == nil {
3949 return err
3950 }
3951 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3952 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3953 defer cancel()
3954 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3955 return err
3956}
3957
khenaidoodc2116e2021-10-19 17:33:19 -04003958func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003959 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3960 if err != nil || aClient == nil {
3961 return err
3962 }
3963 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3964 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3965 defer cancel()
3966 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3967 return err
3968}
3969
khenaidoodc2116e2021-10-19 17:33:19 -04003970func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003971 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3972 if err != nil || aClient == nil {
3973 return err
3974 }
3975 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3976 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3977 defer cancel()
3978 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3979 return err
3980}
3981
3982/*
3983Helper functions for remote communication
3984*/
3985
3986// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3987// supports is deleted
3988func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3989 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3990
3991 dh.lockChildAdapterClients.Lock()
3992 defer dh.lockChildAdapterClients.Unlock()
3993 if _, ok := dh.childAdapterClients[endpoint]; ok {
3994 // Already set
3995 return nil
3996 }
3997
3998 // Setup child's adapter grpc connection
3999 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004000 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4001 dh.cfg.AdapterEndpoint,
4002 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004003 "onu_inter_adapter_service.OnuInterAdapterService",
4004 dh.onuInterAdapterRestarted,
4005 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004006 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4007 return err
4008 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304009 retryCodes := []codes.Code{
4010 codes.Unavailable, // server is currently unavailable
4011 codes.DeadlineExceeded, // deadline for the operation was exceeded
4012 }
4013 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4014 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 -04004015
nikesh.krishnand9812542023-08-01 18:31:39 +05304016 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004017 // Wait until we have a connection to the child adapter.
4018 // Unlimited retries or until context expires
4019 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4020 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4021 for {
4022 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4023 if err == nil && client != nil {
4024 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4025 break
4026 }
4027 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4028 // Backoff
4029 if err = backoff.Backoff(subCtx); err != nil {
4030 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4031 break
4032 }
4033 }
4034 return nil
4035}
4036
khenaidoodc2116e2021-10-19 17:33:19 -04004037func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004038
4039 // First check from cache
4040 dh.lockChildAdapterClients.RLock()
4041 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4042 dh.lockChildAdapterClients.RUnlock()
4043 return cgClient.GetOnuInterAdapterServiceClient()
4044 }
4045 dh.lockChildAdapterClients.RUnlock()
4046
4047 // Set the child connection - can occur on restarts
4048 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4049 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4050 cancel()
4051 if err != nil {
4052 return nil, err
4053 }
4054
4055 // Get the child client now
4056 dh.lockChildAdapterClients.RLock()
4057 defer dh.lockChildAdapterClients.RUnlock()
4058 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4059 return cgClient.GetOnuInterAdapterServiceClient()
4060 }
4061 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4062}
4063
4064func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4065 dh.lockChildAdapterClients.Lock()
4066 defer dh.lockChildAdapterClients.Unlock()
4067 for key, client := range dh.childAdapterClients {
4068 client.Stop(ctx)
4069 delete(dh.childAdapterClients, key)
4070 }
4071}
4072
khenaidooefff76e2021-12-15 16:51:30 -05004073// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4074func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4075 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004076 return nil
4077}
4078
khenaidooefff76e2021-12-15 16:51:30 -05004079// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4080func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4081 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004082 return nil
4083 }
khenaidooefff76e2021-12-15 16:51:30 -05004084 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004085}
Girish Gowdra950326e2021-11-05 12:43:24 -07004086
4087func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4088 dh.lockDevice.Lock()
4089 defer dh.lockDevice.Unlock()
4090 dh.isDeviceDeletionInProgress = flag
4091}
4092
4093func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4094 dh.lockDevice.RLock()
4095 defer dh.lockDevice.RUnlock()
4096 return dh.isDeviceDeletionInProgress
4097}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004098
4099// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4100// Returns false if waiting timed out.
4101func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4102 c := make(chan struct{})
4103 go func() {
4104 defer close(c)
4105 wg.Wait()
4106 }()
4107 select {
4108 case <-c:
4109 return true // completed normally
4110 case <-time.After(timeout):
4111 return false // timed out
4112 }
4113}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304114
4115func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4116 val, err := json.Marshal(signature)
4117 if err != nil {
4118 logger.Error(ctx, "failed-to-marshal")
4119 return
4120 }
4121 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4122 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4123 }
4124}
4125
4126func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4127 var signature uint32
4128
4129 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4130 if er == nil {
4131 if Value != nil {
4132 Val, er := kvstore.ToByte(Value.Value)
4133 if er != nil {
4134 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4135 return signature
4136 }
4137 if er = json.Unmarshal(Val, &signature); er != nil {
4138 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4139 return signature
4140 }
4141 }
4142 }
4143 return signature
4144}