blob: 0686fa322cd9907cd704237dab3c96f3aa3f052f [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
Joey Armstronga6af1522023-01-17 16:06:16 -05002 * Copyright 2018-2023 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
khenaidoo106c61a2021-08-11 18:05:46 -040049 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053050 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080051 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040052 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040053 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040054 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040055 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
56 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040057 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
58 oop "github.com/opencord/voltha-protos/v5/go/openolt"
59 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070060 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040061 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040062 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053063)
64
salmansiddiqui7ac62132019-08-22 03:58:50 +000065// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040066const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080067 InvalidPort = 0xffffffff
68 MaxNumOfGroupHandlerChannels = 256
69
70 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
71 McastFlowOrGroupModify = "McastFlowOrGroupModify"
72 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050073 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010074
75 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053076 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040077)
78
Mahir Gunyela2e68702022-12-07 00:00:42 -080079// DeviceHandler will interact with the OLT device.
Phaneendra Manda4c62c802019-03-06 21:37:49 +053080type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040081 cm *config.ConfigManager
82 device *voltha.Device
83 cfg *conf.AdapterFlags
84 coreClient *vgrpc.Client
85 childAdapterClients map[string]*vgrpc.Client
86 lockChildAdapterClients sync.RWMutex
87 EventProxy eventif.EventProxy
88 openOLT *OpenOLT
khenaidooefff76e2021-12-15 16:51:30 -050089 exitChannel chan struct{}
khenaidoo106c61a2021-08-11 18:05:46 -040090 lockDevice sync.RWMutex
91 Client oop.OpenoltClient
92 transitionMap *TransitionMap
93 clientCon *grpc.ClientConn
94 flowMgr []*OpenOltFlowMgr
95 groupMgr *OpenOltGroupMgr
96 eventMgr *OpenOltEventMgr
97 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053098 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070099
100 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530101
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700102 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
103 // if the value is true that means the OnuDiscovery indication
104 // is currently being processed and thus we can ignore concurrent requests
105 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
106 // if we do it means something went wrong and we need to retry
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700107 discOnus sync.Map
108 onus sync.Map
109 portStats *OpenOltStatisticsMgr
110 metrics *pmmetrics.PmMetrics
111 stopCollector chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000112 isCollectorActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700113 stopHeartbeatCheck chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000114 isHeartbeatCheckActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700115 activePorts sync.Map
116 stopIndications chan bool
117 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700118
Mahir Gunyelb0046752021-02-26 13:51:05 -0800119 totalPonPorts uint32
120 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
121 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800122
123 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
124 // 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 -0700125 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
126 stopMcastHandlerRoutine []chan bool
127 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000128
129 adapterPreviouslyConnected bool
130 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700131
132 isDeviceDeletionInProgress bool
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530133 heartbeatSignature uint32
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134}
135
Mahir Gunyela2e68702022-12-07 00:00:42 -0800136// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700137type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400138 deviceID string
139 deviceType string
140 serialNumber string
141 onuID uint32
142 intfID uint32
143 proxyDeviceID string
144 losRaised bool
145 rdiRaised bool
146 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700147}
148
Mahir Gunyelb0046752021-02-26 13:51:05 -0800149type onuIndicationMsg struct {
150 ctx context.Context
151 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800152}
153
154type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800155 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800156 stopChannel chan struct{}
157}
158
Mahir Gunyela2e68702022-12-07 00:00:42 -0800159// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
160// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
161// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
162// 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 -0800163type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400164 ctx context.Context // Flow/group handler context
165 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
166 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
167 group *of.OfpGroupEntry // Group message (can be nil or valid group)
168 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800169}
170
Naga Manjunath7615e552019-10-11 22:35:47 +0530171var pmNames = []string{
172 "rx_bytes",
173 "rx_packets",
174 "rx_mcast_packets",
175 "rx_bcast_packets",
176 "tx_bytes",
177 "tx_packets",
178 "tx_mcast_packets",
179 "tx_bcast_packets",
180}
181
Mahir Gunyela2e68702022-12-07 00:00:42 -0800182// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400183func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700184 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700185 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700186 device.deviceType = deviceTp
187 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700188 device.onuID = onuID
189 device.intfID = intfID
190 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530191 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400192 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700193 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530194}
195
Mahir Gunyela2e68702022-12-07 00:00:42 -0800196// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400197func 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 -0700198 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530199 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800200 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400201 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400202 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700203 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700204 dh.device = cloned
205 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500206 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700207 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000208 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
209 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530210 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 -0500211 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800212 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800213 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400214 dh.childAdapterClients = make(map[string]*vgrpc.Client)
215 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300216 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530217 if dh.kvStore == nil {
218 logger.Error(ctx, "Failed to setup KV store")
219 return nil
220 }
221
Girish Gowdra491a9c62021-01-06 16:43:07 -0800222 // Create a slice of buffered channels for handling concurrent mcast flow/group.
223 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700224 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
225 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800226 for i := range dh.incomingMcastFlowOrGroup {
227 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800228 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800229 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
230 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
231 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
232 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700233 dh.mcastHandlerRoutineActive[i] = true
234 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800235 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700236 //TODO initialize the support classes.
237 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530238}
239
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530240func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
241 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
242 switch storeType {
243 case "etcd":
244 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
245 }
246 return nil, errors.New("unsupported-kv-store")
247}
248
249// SetKVClient sets the KV client and return a kv backend
250func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
251 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
252 if err != nil {
253 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
254 return nil
255 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530256 kvbackend := &db.Backend{
257 Client: kvClient,
258 StoreType: backend,
259 Address: addr,
260 Timeout: rsrcMgr.KvstoreTimeout,
261 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
262
263 return kvbackend
264}
265
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000266// CloseKVClient closes open KV clients
267func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
268 if dh.resourceMgr != nil {
269 for _, rscMgr := range dh.resourceMgr {
270 if rscMgr != nil {
271 rscMgr.CloseKVClient(ctx)
272 }
273 }
274 }
275 if dh.flowMgr != nil {
276 for _, flMgr := range dh.flowMgr {
277 if flMgr != nil {
278 flMgr.CloseKVClient(ctx)
279 }
280 }
281 }
282}
283
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530284// start save the device to the data model
285func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700286 dh.lockDevice.Lock()
287 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000288 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700289 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000290 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530291}
292
khenaidooefff76e2021-12-15 16:51:30 -0500293// Stop stops the device handler
294func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700295 dh.lockDevice.Lock()
296 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000297 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500298 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400299
khenaidooefff76e2021-12-15 16:51:30 -0500300 // Delete (which will stop also) all grpc connections to the child adapters
301 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000302 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530303}
304
ssiddiqui04386ee2021-08-23 21:58:25 +0530305func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
306 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
307 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
308 if pooledIntfID == intfID {
309 return resourceRanges.GetTechnology()
310 }
311 }
312 }
313 return ""
314}
315
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400316func macifyIP(ip net.IP) string {
317 if len(ip) > 0 {
318 oct1 := strconv.FormatInt(int64(ip[12]), 16)
319 oct2 := strconv.FormatInt(int64(ip[13]), 16)
320 oct3 := strconv.FormatInt(int64(ip[14]), 16)
321 oct4 := strconv.FormatInt(int64(ip[15]), 16)
322 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
323 }
324 return ""
325}
326
Neha Sharma96b7bf22020-06-15 10:37:32 +0000327func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400328 var genmac string
329 var addr net.IP
330 var ips []string
331 var err error
332
Neha Sharma96b7bf22020-06-15 10:37:32 +0000333 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400334
335 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000336 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400337
338 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000339 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400340 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000341 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400342 }
343 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000344 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530345 log.Fields{"host": ips[0],
346 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400347 return genmac, nil
348 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000349 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400350 }
351
352 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000353 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530354 log.Fields{"host": host,
355 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400356 return genmac, nil
357}
358
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530359func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700360 slist := strings.Split(mac, ":")
361 result := make([]uint32, len(slist))
362 var err error
363 var tmp int64
364 for index, val := range slist {
365 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
366 return []uint32{1, 2, 3, 4, 5, 6}
367 }
368 result[index] = uint32(tmp)
369 }
370 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530371}
372
Mahir Gunyela2e68702022-12-07 00:00:42 -0800373// 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 -0800374func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530375
David K. Bainbridge794735f2020-02-11 21:01:37 -0800376 switch portType {
377 case voltha.Port_ETHERNET_NNI:
378 return fmt.Sprintf("nni-%d", portNum), nil
379 case voltha.Port_PON_OLT:
380 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700381 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800382
Girish Kumarf26e4882020-03-05 06:49:10 +0000383 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530384}
385
Elia Battiston596406d2022-02-02 12:19:00 +0100386func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
387 if speedMbps == 0 {
388 //In case it was not set in the indication
389 //and no other value was provided
390 speedMbps = defaultPortSpeedMbps
391 }
392
393 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
394 switch speedMbps {
395 case 1000000:
396 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
397 case 100000:
398 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
399 case 40000:
400 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
401 case 10000:
402 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
403 case 1000:
404 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
405 case 100:
406 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
407 case 10:
408 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
409 }
410
411 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
412
413 port := &of.OfpPort{
414 HwAddr: macAddressToUint32Array(macAddress),
415 Config: 0,
416 State: uint32(of.OfpPortState_OFPPS_LIVE),
417 Curr: capacity,
418 Advertised: capacity,
419 Peer: capacity,
420 CurrSpeed: speedMbps * 1000, //kbps
421 MaxSpeed: speedMbps * 1000, //kbps
422 }
423
424 return port
425}
426
427func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000428 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700429 if state == "up" {
430 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500431 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500432 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700433 } else {
434 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500435 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700436 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700437 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400438 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800439 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000440 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400441 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500442
khenaidoo106c61a2021-08-11 18:05:46 -0400443 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400444 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400445 DeviceId: dh.device.Id,
446 Port: portNum,
447 })
448 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000449 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400450 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400451 DeviceId: dh.device.Id,
452 PortType: portType,
453 PortNo: portNum,
454 OperStatus: operStatus})
455 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400456 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
457 "device-id": dh.device.Id,
458 "port-type": portType,
459 "port-number": portNum,
460 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500461 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400462 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500463 }
khenaidoo106c61a2021-08-11 18:05:46 -0400464
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400465 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400466 port = &voltha.Port{
467 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700468 PortNo: portNum,
469 Label: label,
470 Type: portType,
471 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100472 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700473 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000474 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700475 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400476 err = dh.createPortInCore(ctx, port)
477 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000478 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800479 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000480 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400481 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000482 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530483 return nil
484}
485
Kent Hagermane6ff1012020-07-14 15:07:53 -0400486func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400487 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530488 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400489 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
490 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530491 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800492 dh.lockDevice.Lock()
493 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530494 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530495}
496
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700497// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530498// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800499func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000500 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700501 defer func() {
502 dh.lockDevice.Lock()
503 dh.isReadIndicationRoutineActive = false
504 dh.lockDevice.Unlock()
505 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700506 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700507 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700508 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700509 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400510
David Bainbridgef5879ca2019-12-13 21:17:54 +0000511 // Create an exponential backoff around re-enabling indications. The
512 // maximum elapsed time for the back off is set to 0 so that we will
513 // continue to retry. The max interval defaults to 1m, but is set
514 // here for code clarity
515 indicationBackoff := backoff.NewExponentialBackOff()
516 indicationBackoff.MaxElapsedTime = 0
517 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700518
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700519 dh.lockDevice.Lock()
520 dh.isReadIndicationRoutineActive = true
521 dh.lockDevice.Unlock()
522
Girish Gowdra3f974912020-03-23 20:35:18 -0700523Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700524 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400525 select {
526 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000527 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700528 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400529 default:
530 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100531
532 select {
533 case <-indications.Context().Done():
534 if err != nil {
535 logger.Warnw(ctx, "error-during-enable-indications",
536 log.Fields{"err": err,
537 "device-id": dh.device.Id})
538 }
539
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400540 // Use an exponential back off to prevent getting into a tight loop
541 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100542 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
543 "device-id": dh.device.Id,
544 "duration": duration,
545 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400546 if duration == backoff.Stop {
547 // If we reach a maximum then warn and reset the backoff
548 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100549 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530550 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530551 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400552 indicationBackoff.Reset()
553 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700554
555 // On failure process a backoff timer while watching for stopIndications
556 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700557 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700558 select {
559 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000560 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700561 if !backoffTimer.Stop() {
562 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700563 }
564 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700565 case <-backoffTimer.C:
566 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700567 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700568 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
569 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400570 }
571 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100572 default:
573 if err != nil {
574 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530575 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530576 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100577 // Close the stream, and re-initialize it
578 if err = indications.CloseSend(); err != nil {
579 // Ok to ignore here, because we landed here due to a problem on the stream
580 // In all probability, the closeSend call may fail
581 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
582 log.Fields{"err": err,
583 "device-id": dh.device.Id})
584 }
585 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
586 return err
587 }
588 // once we re-initialized the indication stream, continue to read indications
589 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700590 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100591 // Reset backoff if we have a successful receive
592 indicationBackoff.Reset()
593 // When OLT is admin down, ignore all indications.
594 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
595 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
596 log.Fields{"indication": indication,
597 "device-id": dh.device.Id})
598 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700599 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100600 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530601 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700602 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700603 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700604 // Close the send stream
605 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700606
Girish Gowdra3f974912020-03-23 20:35:18 -0700607 return nil
608}
609
610func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700611 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700612 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
613 if err != nil {
614 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
615 }
616 if indications == nil {
617 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
618 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700619 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700620 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400621}
622
623// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
624func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
625 switch indication.Data.(type) {
626 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
627 return true
628
629 default:
630 return false
631 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700632}
633
David K. Bainbridge794735f2020-02-11 21:01:37 -0800634func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700635 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000636 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530637 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700638 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530639 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000641 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000642 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530643 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000644 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800645 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000646 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800647 }
648 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649}
650
David K. Bainbridge794735f2020-02-11 21:01:37 -0800651// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530652func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700653 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700654 switch indication.Data.(type) {
655 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000656 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
657 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700658 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 -0800659 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400660 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800661 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000663 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
664 defer span.Finish()
665
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700666 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800667 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100668 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400669 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800670 }
671 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000672 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700673 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000674 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
675 defer span.Finish()
676
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700677 intfOperInd := indication.GetIntfOperInd()
678 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800679 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100680 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400681 _ = 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 -0800682 }
683 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700684 } else if intfOperInd.GetType() == "pon" {
685 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
686 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800687 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100688 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400689 _ = 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 -0800690 }
691 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000692 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700693 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000694 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530695 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530696 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000698 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
699 defer span.Finish()
700
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800703 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800704 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000706 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
707 defer span.Finish()
708
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700709 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000710 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800711 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800712 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700713 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000714 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
715 defer span.Finish()
716
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700717 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000718 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 -0800719 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000720 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400721 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800722 }
723 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700724 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000725 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
726 defer span.Finish()
727
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700728 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000729 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700730 "intf-type": pktInd.IntfId,
731 "intf-id": pktInd.IntfId,
732 "gem-port-id": pktInd.GemportId,
733 "port-no": pktInd.PortNo,
734 "device-id": dh.device.Id,
735 })
736
737 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000738 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700739 "intf-type": pktInd.IntfId,
740 "intf-id": pktInd.IntfId,
741 "gem-port-id": pktInd.GemportId,
742 "port-no": pktInd.PortNo,
743 "packet": hex.EncodeToString(pktInd.Pkt),
744 "device-id": dh.device.Id,
745 })
746 }
747
David K. Bainbridge794735f2020-02-11 21:01:37 -0800748 go func() {
749 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400750 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800751 }
752 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700753 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000754 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
755 defer span.Finish()
756
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700757 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700758 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000760 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
761 defer span.Finish()
762
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700763 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000764 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700765 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000766 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
767 defer span.Finish()
768
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000770 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
771 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700772 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530773}
774
775// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530776func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530777 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000778 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530779
Girish Gowdra618fa572021-09-01 17:19:29 -0700780 // instantiate the mcast handler routines.
781 for i := range dh.incomingMcastFlowOrGroup {
782 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
783 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
784 if !dh.mcastHandlerRoutineActive[i] {
785 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
786 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
787 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
788 // for incoming mcast flow/group to be processed serially.
789 dh.mcastHandlerRoutineActive[i] = true
790 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
791 }
792 }
793
Girish Gowdru0c588b22019-04-23 23:24:56 -0400794 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400795 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400796 DeviceId: dh.device.Id,
797 OperStatus: voltha.OperStatus_ACTIVE,
798 ConnStatus: voltha.ConnectStatus_REACHABLE,
799 }); err != nil {
800 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400801 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000802
803 //Clear olt communication failure event
804 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
805 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700806 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000807 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
808
Girish Gowdru0c588b22019-04-23 23:24:56 -0400809 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530810}
811
812// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530813func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000814 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400815
khenaidoo106c61a2021-08-11 18:05:46 -0400816 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400817 if err != nil || device == nil {
818 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000819 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400820 }
821
822 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400823
824 //Update the device oper state and connection status
825 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800826 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400827 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800828 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400829
khenaidoodc2116e2021-10-19 17:33:19 -0400830 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400831 DeviceId: cloned.Id,
832 OperStatus: cloned.OperStatus,
833 ConnStatus: cloned.ConnectStatus,
834 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000835 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400836 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400837
838 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400839 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400840 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000841 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400842 }
843 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400844 // Update onu state as down in onu adapter
845 onuInd := oop.OnuIndication{}
846 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400847
848 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
849 if err != nil {
850 return err
851 }
852 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400853 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400854 DeviceId: onuDevice.Id,
855 OnuIndication: &onuInd,
856 })
857 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800858 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400859 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400860 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800861 "onu-indicator": onuInd,
862 "device-type": onuDevice.Type,
863 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700864 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800865 } else {
866 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 -0700867 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400868 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800869 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700870 /* Discovered ONUs entries need to be cleared , since after OLT
871 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530872 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800873 dh.lockDevice.Unlock()
874
Neha Sharma96b7bf22020-06-15 10:37:32 +0000875 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700876 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530877}
878
879// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530880func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400881 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000882
883 // if the connection is already available, close the previous connection (olt reboot case)
884 if dh.clientCon != nil {
885 if err = dh.clientCon.Close(); err != nil {
886 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
887 } else {
888 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
889 }
890 }
891
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530892 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +0000893 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000894 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
895 grpc.WithInsecure(),
896 grpc.WithBlock(),
897 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000898 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000899 )),
900 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000901 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000902 )))
903
904 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530905 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530906 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000907 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400908 }
909 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530910}
911
912// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530913func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400914 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530915 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400916 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530917}
918
919// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530920func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530921 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000922 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400923
924 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400925 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530926 if err != nil || device == nil {
927 /*TODO: needs to handle error scenarios */
928 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
929 }
930 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000931 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400932
933 cloned := proto.Clone(device).(*voltha.Device)
934 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
935 cloned.OperStatus = voltha.OperStatus_UNKNOWN
936 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400937
khenaidoodc2116e2021-10-19 17:33:19 -0400938 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400939 DeviceId: cloned.Id,
940 OperStatus: cloned.OperStatus,
941 ConnStatus: cloned.ConnectStatus,
942 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530943 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 -0400944 }
945
Chaitrashree G S44124192019-08-07 20:21:36 -0400946 // 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 +0530947 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400948 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530949 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400950 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400951 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
952 // all the modules initialized and ready to handle incoming ONUs.
953
Thomas Lee S985938d2020-05-04 11:40:41 +0530954 err = dh.initializeDeviceHandlerModules(ctx)
955 if err != nil {
956 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 -0400957 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400958
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700959 go startHeartbeatCheck(ctx, dh)
960
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400961 return nil
962 }
963
khenaidoo106c61a2021-08-11 18:05:46 -0400964 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400965 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400966 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400967 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400968 }
khenaidoo106c61a2021-08-11 18:05:46 -0400969 dh.populateActivePorts(ctx, ports.Items)
970 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400971 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400972 }
973
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400974 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530975 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 -0400976 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530977
Neha Sharma96b7bf22020-06-15 10:37:32 +0000978 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000979
980 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000981 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000982 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700983
984 go startHeartbeatCheck(ctx, dh)
985
cuilin20187b2a8c32019-03-26 19:52:28 -0700986 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530987}
988
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400989func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700990 var err error
991 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400992
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000993 if dh.flowMgr != nil {
994 dh.StopAllFlowRoutines(ctx)
995 }
996
997 dh.CloseKVClient(ctx)
998
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400999 if err != nil {
1000 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1001 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001002 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1003 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +00001004 // +1 is for NNI
1005 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1006 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001007 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001008 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1009 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1010 // There is only one NNI manager since multiple NNI is not supported for now
1011 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001012 // Instantiate resource manager
1013 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 -07001014 return olterrors.ErrResourceManagerInstantiating
1015 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001016 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001017 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1018 // the KV store to manage mcast group data. Provide the first instance (0th index)
1019 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1020 return olterrors.ErrGroupManagerInstantiating
1021 }
yasin saplid0566272021-12-21 09:10:30 +00001022 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001023 // Instantiate flow manager
1024 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001025 //Continue to check the rest of the ports
1026 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1027 } else {
1028 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001029 }
1030 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001031 /* TODO: Instantiate Alarm , stats , BW managers */
1032 /* Instantiating Event Manager to handle Alarms and KPIs */
1033 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1034
1035 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001036 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001037
1038 return nil
1039
1040}
1041
Neha Sharma96b7bf22020-06-15 10:37:32 +00001042func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001043 var err error
1044 var deviceInfo *oop.DeviceInfo
1045
Neha Sharma8f4e4322020-08-06 10:51:53 +00001046 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001047
1048 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001049 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001050 }
1051 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001052 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001053 }
1054
Neha Sharma96b7bf22020-06-15 10:37:32 +00001055 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001056 dh.device.Root = true
1057 dh.device.Vendor = deviceInfo.Vendor
1058 dh.device.Model = deviceInfo.Model
1059 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1060 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1061 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1062
1063 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001064 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001065 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001066 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001067 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001068 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001069 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001070 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001071 dh.device.MacAddress = genmac
1072 } else {
1073 dh.device.MacAddress = deviceInfo.DeviceId
1074 }
1075
1076 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001077 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001078 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001079 }
1080
1081 return deviceInfo, nil
1082}
1083
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001085 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001086
1087 defer func() {
1088 dh.lockDevice.Lock()
1089 dh.isCollectorActive = false
1090 dh.lockDevice.Unlock()
1091 }()
1092
1093 dh.lockDevice.Lock()
1094 dh.isCollectorActive = true
1095 dh.lockDevice.Unlock()
1096
Naga Manjunath7615e552019-10-11 22:35:47 +05301097 for {
1098 select {
1099 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001100 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301101 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001102 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001103
khenaidoo106c61a2021-08-11 18:05:46 -04001104 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001105 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001106 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001107 continue
1108 }
khenaidoo106c61a2021-08-11 18:05:46 -04001109 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301110 // NNI Stats
1111 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001112 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301113 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001114 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001115 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001116 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301117 }
1118 // PON Stats
1119 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001120 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301121 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1122 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001123 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001124 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301125 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001126 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001127
yasin sapli9e4c5092022-02-01 13:52:33 +00001128 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001129 if len(onuGemInfoLst) > 0 {
1130 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001131 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001132 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301133 }
1134 }
1135 }
1136}
1137
Mahir Gunyela2e68702022-12-07 00:00:42 -08001138// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301139func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001140 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001141 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301142 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301143
1144 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001145 cgClient, err := dh.coreClient.GetCoreServiceClient()
1146 if err != nil {
1147 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1148 return
1149 }
1150
1151 // Now, set the initial PM configuration for that device
1152 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001153 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301154 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301155}
1156
Mahir Gunyela2e68702022-12-07 00:00:42 -08001157// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001158func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1159 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001160 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301161 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001162 HwDesc: "open_pon",
1163 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001164 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001165 },
1166 SwitchFeatures: &of.OfpSwitchFeatures{
1167 NBuffers: 256,
1168 NTables: 2,
1169 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1170 of.OfpCapabilities_OFPC_TABLE_STATS |
1171 of.OfpCapabilities_OFPC_PORT_STATS |
1172 of.OfpCapabilities_OFPC_GROUP_STATS),
1173 },
1174 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301175}
1176
khenaidoo106c61a2021-08-11 18:05:46 -04001177// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001178func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001179 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001180 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001181 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001182 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001183 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1184 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()
1185 }
khenaidoo106c61a2021-08-11 18:05:46 -04001186 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Mahir Gunyela2e68702022-12-07 00:00:42 -08001187
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001188}
1189
Neha Sharma96b7bf22020-06-15 10:37:32 +00001190func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001191 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 -07001192 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001193 var deviceID string
1194 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001195 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001196
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001197 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001198 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001199 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 -07001200 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1201 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001202
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001203 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301204
1205 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1206
Neha Sharma96b7bf22020-06-15 10:37:32 +00001207 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 -07001208 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001209
khenaidoodc2116e2021-10-19 17:33:19 -04001210 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001211 ParentId: dh.device.Id,
1212 OnuId: omciInd.OnuId,
1213 ParentPortNo: ponPort,
1214 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001215 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301216 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001217 "intf-id": omciInd.IntfId,
1218 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001219 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001220 deviceType = onuDevice.Type
1221 deviceID = onuDevice.Id
1222 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001223 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001224 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001225 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001226 } else {
1227 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001228 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 +05301229 deviceType = onuInCache.(*OnuDevice).deviceType
1230 deviceID = onuInCache.(*OnuDevice).deviceID
1231 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001232 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001233 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001234
khenaidoodc2116e2021-10-19 17:33:19 -04001235 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001236 ParentDeviceId: proxyDeviceID,
1237 ChildDeviceId: deviceID,
1238 Message: omciInd.Pkt,
1239 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301240 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001241 "source": dh.openOLT.config.AdapterEndpoint,
1242 "device-type": deviceType,
1243 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001245 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001246 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001247 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301248}
1249
khenaidoo106c61a2021-08-11 18:05:46 -04001250// //ProcessInterAdapterMessage sends the proxied messages to the target device
1251// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1252// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001253// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001254// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001255// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001256// return dh.handleInterAdapterOmciMsg(ctx, msg)
1257// }
1258// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1259// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001260
kesavandb9f54fd2021-11-25 20:08:04 +05301261// ProxyOmciRequests sends the proxied OMCI message to the target device
1262func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301263 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1264 return status.Error(codes.Unavailable, "OLT unreachable")
1265 }
kesavandb9f54fd2021-11-25 20:08:04 +05301266 if omciMsgs.GetProxyAddress() == nil {
1267 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1268 if err != nil {
1269 return olterrors.NewErrNotFound("onu", log.Fields{
1270 "parent-device-id": dh.device.Id,
1271 "child-device-id": omciMsgs.ChildDeviceId}, err)
1272 }
1273 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1274 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1275 return olterrors.NewErrCommunication("send-failed", log.Fields{
1276 "parent-device-id": dh.device.Id,
1277 "child-device-id": omciMsgs.ChildDeviceId}, err)
1278 }
1279 } else {
1280 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1281 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1282 return olterrors.NewErrCommunication("send-failed", log.Fields{
1283 "parent-device-id": dh.device.Id,
1284 "child-device-id": omciMsgs.ChildDeviceId}, err)
1285 }
1286 }
1287 return nil
1288}
1289
1290func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1291 var intfID uint32
1292 var onuID uint32
1293 var connectStatus common.ConnectStatus_Types
1294 if onuDevice != nil {
1295 intfID = onuDevice.ProxyAddress.GetChannelId()
1296 onuID = onuDevice.ProxyAddress.GetOnuId()
1297 connectStatus = onuDevice.ConnectStatus
1298 } else {
1299 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1300 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1301 connectStatus = omciMsgs.GetConnectStatus()
1302 }
1303 if connectStatus != voltha.ConnectStatus_REACHABLE {
1304 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1305
1306 return olterrors.NewErrCommunication("unreachable", log.Fields{
1307 "intf-id": intfID,
1308 "onu-id": onuID}, nil)
1309 }
1310
1311 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1312 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1313
1314 onuSecOmciMsgList := omciMsgs.GetMessages()
1315
1316 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1317
1318 var omciMessage *oop.OmciMsg
1319 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1320 hex.Encode(hexPkt, onuSecOmciMsg)
1321 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1322
1323 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1324 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1325 //https://jira.opencord.org/browse/VOL-4604
1326 transid := extractOmciTransactionID(onuSecOmciMsg)
1327 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1328 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1329
1330 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1331 if err != nil {
1332 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1333 "intf-id": intfID,
1334 "onu-id": onuID,
1335 "message": omciMessage}, err)
1336 }
1337 }
1338 return nil
1339}
1340
khenaidoo106c61a2021-08-11 18:05:46 -04001341// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001342func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001343 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 -07001344
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301345 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1346 return status.Error(codes.Unavailable, "OLT unreachable")
1347 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001348 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001349 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001350 if err != nil {
1351 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001352 "parent-device-id": dh.device.Id,
1353 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001354 }
khenaidoo106c61a2021-08-11 18:05:46 -04001355 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1356 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001357 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001358 "parent-device-id": dh.device.Id,
1359 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001360 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001361 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001362 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1363 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001364 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001365 "parent-device-id": dh.device.Id,
1366 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001367 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001368 }
1369 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301370}
1371
khenaidoodc2116e2021-10-19 17:33:19 -04001372func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001373 var intfID uint32
1374 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001375 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001376 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001377 intfID = onuDevice.ProxyAddress.GetChannelId()
1378 onuID = onuDevice.ProxyAddress.GetOnuId()
1379 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001380 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001381 intfID = omciMsg.GetProxyAddress().GetChannelId()
1382 onuID = omciMsg.GetProxyAddress().GetOnuId()
1383 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001384 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001385 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001386 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 -08001387
Thomas Lee S94109f12020-03-03 16:39:29 +05301388 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001389 "intf-id": intfID,
1390 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001391 }
1392
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001393 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1394 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301395 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001396 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001397 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1398 hex.Encode(hexPkt, omciMsg.Message)
1399 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1400
1401 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1402 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1403 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001404 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001405 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001406
Neha Sharma8f4e4322020-08-06 10:51:53 +00001407 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001408 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301409 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001410 "intf-id": intfID,
1411 "onu-id": onuID,
1412 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001413 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001415}
1416
David K. Bainbridge794735f2020-02-11 21:01:37 -08001417func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301418 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 +00001419 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001420 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001421 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001422 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301423 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301424 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001425 st, _ := status.FromError(err)
1426 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001427 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1428
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001429 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301430 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001431 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001432 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001433 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001434 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001435 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001436}
1437
Mahir Gunyela2e68702022-12-07 00:00:42 -08001438// getChildDevice function can be used in general to get child device, if not found in cache the function will
1439// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301440func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1441 var InCacheOnuDev *OnuDevice
1442 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1443 if onuInCache.(*OnuDevice).serialNumber == sn {
1444 InCacheOnuDev = onuInCache.(*OnuDevice)
1445 return false
1446 }
1447 return true
1448 })
1449 //Got the onu device from cache return
1450 if InCacheOnuDev != nil {
1451 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1452 return InCacheOnuDev
1453 }
1454 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1455 ParentId: dh.device.Id,
1456 SerialNumber: sn,
1457 ParentPortNo: parentPortNo,
1458 })
1459 //No device found in core return nil
1460 if onuDevice == nil {
1461 return nil
1462 }
1463 onuID := onuDevice.ProxyAddress.OnuId
1464 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1465 onuKey := dh.formOnuKey(intfID, onuID)
1466
1467 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1468 dh.onus.Store(onuKey, onuDev)
1469 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1470 return onuDev
1471}
1472
1473func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001474 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001475 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301476 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001477
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301478 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1479 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1480 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1481 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1482 if onuDev != nil {
1483 var onuGemInfo *rsrcMgr.OnuGemInfo
1484 var err error
1485 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1486 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1487 return false, err
1488 }
1489 if onuGemInfo != nil {
1490 for _, uni := range onuGemInfo.UniPorts {
1491 uniID := plt.UniIDFromPortNum(uni)
1492 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1493 if len(tpIDs) != 0 {
1494 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1495 tpInstExists = true
1496 break
1497 }
1498 }
1499 }
1500 }
1501 return tpInstExists, nil
1502 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301503
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301504 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1505 ParentId: dh.device.Id,
1506 SerialNumber: sn,
1507 ParentPortNo: parentPortNo,
1508 })
1509 if onuDevice != nil {
1510 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1511 return true, nil
1512 }
1513 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1514
1515 return false, nil
1516
1517}
1518
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001519// processDiscONULOSClear clears the LOS Alarm if it's needed
1520func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301521 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001522 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301523
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001524 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1525 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1526 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1527 OnuLosRaise event sent for it */
1528 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1529 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1530 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1531 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1532 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1533 "currentIntfId": onuDiscInd.GetIntfId()})
1534 // TODO:: Should we need to ignore raising OnuLosClear event
1535 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301536 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001537 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1538 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1539 alarmInd.LosStatus = statusCheckOff
1540 go func() {
1541 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1542 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1543 }
1544 }()
1545 // stop iterating
1546 return false
1547 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301548 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001549 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301550}
1551
1552func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
1553 channelID := onuDiscInd.GetIntfId()
1554 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1555
1556 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
1557 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1558
1559 tpInstExists, errtp := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1560 if errtp != nil {
1561 return errtp
1562 }
1563 if tpInstExists {
1564 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001565 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001566 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001567 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001568 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1569
1570 // if the ONU existed, handle the LOS Alarm
1571 if existing {
1572
1573 if inProcess.(bool) {
1574 // if we're currently processing the ONU on a different thread, do nothing
1575 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1576 return nil
1577 }
1578 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1579 // then continue processing it
1580 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1581
1582 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001583 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301584 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001585
1586 defer func() {
1587 // once the function completes set the value to false so that
1588 // we know the processing has inProcess.
1589 // Note that this is done after checking if we are already processing
1590 // to avoid changing the value from a different thread
1591 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1592 dh.discOnus.Store(sn, false)
1593 }()
1594
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001595 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001596
1597 // check the ONU is already know to the OLT
1598 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001599 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001600 ParentId: dh.device.Id,
1601 SerialNumber: sn,
1602 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001603
1604 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001605 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001606 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001607 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 -08001608 switch e.Code() {
1609 case codes.Internal:
1610 // this probably means NOT FOUND, so just create a new device
1611 onuDevice = nil
1612 case codes.DeadlineExceeded:
1613 // if the call times out, cleanup and exit
1614 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001615 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001616 }
1617 }
1618 }
1619
1620 if onuDevice == nil {
1621 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001622 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001623 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001624 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001625 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001626
Neha Sharma96b7bf22020-06-15 10:37:32 +00001627 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001628
1629 if err != nil {
1630 // if we can't create an ID in resource manager,
1631 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001632 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001633 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001634 "pon-intf-id": ponintfid,
1635 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001636 }
1637
khenaidoodc2116e2021-10-19 17:33:19 -04001638 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001639 ParentId: dh.device.Id,
1640 ParentPortNo: parentPortNo,
1641 ChannelId: channelID,
1642 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1643 SerialNumber: sn,
1644 OnuId: onuID,
1645 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001646 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001647 dh.resourceMgr[ponintfid].FreeonuID(ctx, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301648 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001649 "pon-intf-id": ponintfid,
1650 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001651 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001652 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001653 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001654 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001655 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301656 log.Fields{"onuDevice": onuDevice,
1657 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001658 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301659 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001660 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001661
khenaidoo106c61a2021-08-11 18:05:46 -04001662 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1663 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1664 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1665 cancel()
1666 if err != nil {
1667 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1668 }
1669
Matteo Scandolo945e4012019-12-12 14:16:11 -08001670 // we can now use the existing ONU Id
1671 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001672 //Insert the ONU into cache to use in OnuIndication.
1673 //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 +00001674 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001675 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301676 "intfId": onuDiscInd.GetIntfId(),
1677 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001678 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001679
khenaidoo106c61a2021-08-11 18:05:46 -04001680 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301681 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001682 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301683 log.Fields{"onu": onuDev,
1684 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001685
khenaidoodc2116e2021-10-19 17:33:19 -04001686 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001687 DeviceId: onuDevice.Id,
1688 ParentDeviceId: dh.device.Id,
1689 OperStatus: common.OperStatus_DISCOVERED,
1690 ConnStatus: common.ConnectStatus_REACHABLE,
1691 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301692 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001693 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001694 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001695 }
khenaidoo106c61a2021-08-11 18:05:46 -04001696
Neha Sharma96b7bf22020-06-15 10:37:32 +00001697 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001698 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301699 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001700 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001701 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 }
1703 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001704}
1705
Mahir Gunyelb0046752021-02-26 13:51:05 -08001706func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001707
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001708 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001709 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001710 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001711 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001712 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301713 log.Fields{"onuId": onuInd.OnuId,
1714 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301715 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001716 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001717 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301718
David K. Bainbridge794735f2020-02-11 21:01:37 -08001719 errFields := log.Fields{"device-id": dh.device.Id}
1720
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301721 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1722
Mahir Gunyele77977b2019-06-27 05:36:22 -07001723 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1724 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001725 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001726 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001727 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001728 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1729 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001730 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001731 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001732 errFields["onu-id"] = onuInd.OnuId
1733 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001734 }
khenaidoodc2116e2021-10-19 17:33:19 -04001735 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001736 ParentId: dh.device.Id,
1737 SerialNumber: serialNumber,
1738 OnuId: onuInd.OnuId,
1739 ParentPortNo: ponPort,
1740 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001741 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001742
David K. Bainbridge794735f2020-02-11 21:01:37 -08001743 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001744 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001745 }
1746
David K. Bainbridge794735f2020-02-11 21:01:37 -08001747 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001748 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001749 "previousIntfId": onuDevice.ParentPortNo,
1750 "currentIntfId": ponPort})
1751 }
1752
1753 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301755 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1756 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301757 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001758 }
1759 if !foundInCache {
1760 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1761
khenaidoo106c61a2021-08-11 18:05:46 -04001762 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 -08001763
1764 }
kesavand7cf3a052020-08-28 12:49:18 +05301765 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001766 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001767 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301768 }
1769 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001770 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001771 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001772 }
1773 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001774}
1775
Neha Sharma96b7bf22020-06-15 10:37:32 +00001776func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001777 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 -07001778 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1779 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1780 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1781 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001782 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001783 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1784 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001785 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001786 onuInd.OperState = "down"
1787 }
1788 }
1789
David K. Bainbridge794735f2020-02-11 21:01:37 -08001790 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001791 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001792 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 -04001793
khenaidoodc2116e2021-10-19 17:33:19 -04001794 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001795 DeviceId: onuDevice.Id,
1796 OnuIndication: onuInd,
1797 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001798 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301799 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001800 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001801 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001802 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001803 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001804 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001805 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001806 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001807 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001808 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001809}
1810
cuilin20187b2a8c32019-03-26 19:52:28 -07001811func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1812 if serialNum != nil {
1813 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001814 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001815 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001816}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001817func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1818 decodedStr, err := hex.DecodeString(serialNum[4:])
1819 if err != nil {
1820 return nil, err
1821 }
1822 return &oop.SerialNumber{
1823 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001824 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001825 }, nil
1826}
cuilin20187b2a8c32019-03-26 19:52:28 -07001827
1828func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001829 if len(vendorSpecific) > 3 {
1830 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1831 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1832 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1833 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1834 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1835 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1836 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1837 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1838 return tmp
1839 }
1840 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001841}
1842
Mahir Gunyela2e68702022-12-07 00:00:42 -08001843// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001844func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301845 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001846}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001847
Mahir Gunyela2e68702022-12-07 00:00:42 -08001848// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1850 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301851 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001852 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301853 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001854
khenaidoodc2116e2021-10-19 17:33:19 -04001855 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001856 ParentId: dh.device.Id,
1857 OnuId: onuID,
1858 ParentPortNo: parentPort,
1859 })
1860
Girish Gowdru0c588b22019-04-23 23:24:56 -04001861 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001862 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001863 "intf-id": parentPort,
1864 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001865 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001866 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 -08001867 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301868}
1869
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001870// SendPacketInToCore sends packet-in to core
1871// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1872// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001873func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001874 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001876 "port": logicalPort,
1877 "packet": hex.EncodeToString(packetPayload),
1878 "device-id": dh.device.Id,
1879 })
1880 }
khenaidoo106c61a2021-08-11 18:05:46 -04001881
khenaidoodc2116e2021-10-19 17:33:19 -04001882 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001883 DeviceId: dh.device.Id,
1884 Port: logicalPort,
1885 Packet: packetPayload,
1886 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301887 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001888 "source": "adapter",
1889 "destination": "core",
1890 "device-id": dh.device.Id,
1891 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001892 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001893 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001894 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001895 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001896 "packet": hex.EncodeToString(packetPayload),
1897 "device-id": dh.device.Id,
1898 })
1899 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001900 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001901}
1902
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001903// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001904func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001905 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001906
1907 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1908 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001909 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001910 }
1911
Kent Hagermane6ff1012020-07-14 15:07:53 -04001912 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001913 metrics := dh.metrics.GetSubscriberMetrics()
1914 for _, m := range pmConfigs.Metrics {
1915 metrics[m.Name].Enabled = m.Enabled
1916
1917 }
1918 }
1919}
1920
khenaidoodc2116e2021-10-19 17:33:19 -04001921func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001922 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001923 var errorsList []error
1924
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001925 if dh.getDeviceDeletionInProgressFlag() {
1926 // The device itself is going to be reset as part of deletion. So nothing to be done.
1927 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1928 return nil
1929 }
1930
Girish Gowdru0c588b22019-04-23 23:24:56 -04001931 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001932 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001933 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001934
Neha Sharma96b7bf22020-06-15 10:37:32 +00001935 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301936 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001937 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301938 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001939 if flow_utils.HasGroup(flow) {
1940 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1941 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001942 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
1943 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1944 } else {
1945 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
1946 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001947 }
Girish Gowdracefae192020-03-19 18:14:10 -07001948 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01001949 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
1950 //The flow we want to remove is not there, there is no need to throw an error
1951 logger.Warnw(ctx, "flow-to-remove-not-found",
1952 log.Fields{
1953 "ponIf": intfID,
1954 "flowToRemove": flow,
1955 "error": err,
1956 })
1957 } else {
1958 errorsList = append(errorsList, err)
1959 }
Girish Gowdracefae192020-03-19 18:14:10 -07001960 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001961 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301962
1963 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00001964 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001965 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301966 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001967 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301968 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001969 if flow_utils.HasGroup(flow) {
1970 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1971 } else {
yasin saplid0566272021-12-21 09:10:30 +00001972 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001973 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1974 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1975 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1976 } else {
yasin saplid0566272021-12-21 09:10:30 +00001977 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001978 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001979 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001980 if err != nil {
1981 errorsList = append(errorsList, err)
1982 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301983 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001984 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001985
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001986 return errorsList
1987}
1988
1989func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1990 var err error
1991 var errorsList []error
1992
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001993 if dh.getDeviceDeletionInProgressFlag() {
1994 // The device itself is going to be reset as part of deletion. So nothing to be done.
1995 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1996 return nil
1997 }
1998
Girish Gowdracefae192020-03-19 18:14:10 -07001999 // 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 +00002000 if groups != nil {
2001 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002002 // err = dh.groupMgr.AddGroup(ctx, group)
2003 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002004 if err != nil {
2005 errorsList = append(errorsList, err)
2006 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002007 }
2008 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002009 // err = dh.groupMgr.ModifyGroup(ctx, group)
2010 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002011 if err != nil {
2012 errorsList = append(errorsList, err)
2013 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002014 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002015 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002016 // err = dh.groupMgr.DeleteGroup(ctx, group)
2017 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002018 if err != nil {
2019 errorsList = append(errorsList, err)
2020 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002021 }
2022 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002023
2024 return errorsList
2025}
2026
Mahir Gunyela2e68702022-12-07 00:00:42 -08002027// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002028func (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 -07002029
2030 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002031
2032 if dh.getDeviceDeletionInProgressFlag() {
2033 // The device itself is going to be reset as part of deletion. So nothing to be done.
2034 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2035 return nil
2036 }
2037
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002038 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2039 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2040 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002041 if len(errorsList) > 0 {
2042 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2043 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002044 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002045 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302046}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002047
Mahir Gunyela2e68702022-12-07 00:00:42 -08002048// DisableDevice disables the given device
2049// It marks the following for the given device:
2050// Device-Handler Admin-State : down
2051// Device Port-State: UNKNOWN
2052// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002053func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002054 /* On device disable ,admin state update has to be done prior sending request to agent since
2055 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002056 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002057 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002058 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002059 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002060 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002061 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002062 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002063 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002064 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002065 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302066
2067 dh.discOnus = sync.Map{}
2068 dh.onus = sync.Map{}
2069
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002070 dh.lockDevice.RLock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302071 //stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002072 if dh.isCollectorActive {
2073 dh.stopCollector <- true
2074 }
2075 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302076
Neha Sharma96b7bf22020-06-15 10:37:32 +00002077 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002078 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05302079 //Update device Admin state
2080 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002081
kdarapu1afeceb2020-02-12 01:38:09 -05002082 // 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 -04002083 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002084 DeviceId: cloned.Id,
2085 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2086 OperStatus: voltha.OperStatus_UNKNOWN,
2087 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002088 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002089 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002090 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002091 return nil
2092}
2093
Neha Sharma96b7bf22020-06-15 10:37:32 +00002094func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002095 // Update onu state as unreachable in onu adapter
2096 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302097 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002098
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002099 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002100 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002101 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002102 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 -04002103 }
2104 if onuDevices != nil {
2105 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002106 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002107 DeviceId: onuDevice.Id,
2108 OnuIndication: &onuInd,
2109 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002110 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002111 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002112 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002113 }
2114
2115 }
2116 }
2117
2118}
2119
Mahir Gunyela2e68702022-12-07 00:00:42 -08002120// ReenableDevice re-enables the olt device after disable
2121// It marks the following for the given device:
2122// Device-Handler Admin-State : up
2123// Device Port-State: ACTIVE
2124// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002126 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302127 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002128 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302129 }
2130 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002131 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002132
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002133 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002134 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002135 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002136 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002137 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2138 } else {
2139 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2140 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2141 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002142 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002143 if retError == nil {
2144 //Update the device oper status as ACTIVE
2145 device.OperStatus = voltha.OperStatus_ACTIVE
2146 } else {
2147 //Update the device oper status as FAILED
2148 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002149 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002150 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002151
khenaidoodc2116e2021-10-19 17:33:19 -04002152 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002153 DeviceId: device.Id,
2154 OperStatus: device.OperStatus,
2155 ConnStatus: device.ConnectStatus,
2156 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302157 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002158 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002159 "connect-status": device.ConnectStatus,
2160 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002161 }
kesavand39e0aa32020-01-28 20:58:50 -05002162
Neha Sharma96b7bf22020-06-15 10:37:32 +00002163 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002164
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002165 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002166}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002167
npujarec5762e2020-01-01 14:08:48 +05302168func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002169 var uniID uint32
2170 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002171 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302172 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002173 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002174 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002175 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002176 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2177 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2178 } else {
2179 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2180 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002181 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002182 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002183 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002185 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002186 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002187 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002188 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002189 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002190 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002191 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002192 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002193 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002194 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002195 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002196 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302197 }
yasin saplibddc2d72022-02-08 13:10:17 +00002198 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2199 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002200 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002201 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302202 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002203 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002204 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002205 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 -03002206 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002207 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002208 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002209 if len(errs) > 0 {
2210 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2211 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2212 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002213 return nil
2214}
2215
Devmalya Paul495b94a2019-08-27 19:42:00 -04002216// 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 +05302217func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002218 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002219 /* Clear the KV store data associated with the all the UNI ports
2220 This clears up flow data and also resource map data for various
2221 other pon resources like alloc_id and gemport_id
2222 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002223
2224 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002225
2226 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002227
Gustavo Silva41af9122022-10-11 11:05:13 -03002228 err := dh.cleanupDeviceResources(ctx)
2229 if err != nil {
2230 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2231 } else {
2232 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2233 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002234
Himani Chawla49a5d562020-11-25 11:53:44 +05302235 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002236 // Stop the Stats collector
2237 if dh.isCollectorActive {
2238 dh.stopCollector <- true
2239 }
2240 // stop the heartbeat check routine
2241 if dh.isHeartbeatCheckActive {
2242 dh.stopHeartbeatCheck <- true
2243 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302244 // Stop the read indication only if it the routine is active
2245 if dh.isReadIndicationRoutineActive {
2246 dh.stopIndications <- true
2247 }
2248 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002249 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002250 //Reset the state
2251 if dh.Client != nil {
2252 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002253 go func() {
2254 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
2255 if err = dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err != nil {
2256 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
2257 }
2258 }()
2259 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002260 }
2261 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002262 // There is no need to update the core about operation status and connection status of the OLT.
2263 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2264 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2265 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002266
khenaidoo7eb2d672021-10-22 19:08:50 -04002267 // Stop the adapter grpc clients for that parent device
2268 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002269 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002270}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002271
2272// StopAllFlowRoutines stops all flow routines
2273func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2274 var wg sync.WaitGroup
2275 wg.Add(1) // for the mcast routine below to finish
2276 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2277 for _, flMgr := range dh.flowMgr {
2278 if flMgr != nil {
2279 wg.Add(1) // for the flow handler routine below to finish
2280 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2281 }
2282 }
2283 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2284 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2285 } else {
2286 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2287 }
2288}
2289
Gustavo Silva41af9122022-10-11 11:05:13 -03002290func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2291 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002292 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302293 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002294 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002295 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002296 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002297 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002298 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2299 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302300 }
2301 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002302 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2303 errs = append(errs, err)
2304 }
2305 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2306 errs = append(errs, err)
2307 }
2308 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2309 errs = append(errs, err)
2310 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002311 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002312 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002313 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002314 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002315 }
2316 // Clean up NNI manager's data
2317 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2318 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002319 }
A R Karthick1f85b802019-10-11 05:06:05 +00002320
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002321 dh.CloseKVClient(ctx)
2322
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002323 // Take one final sweep at cleaning up KV store for the OLT device
2324 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002325 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2326 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002327 }
2328
Devmalya Paul495b94a2019-08-27 19:42:00 -04002329 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302330 dh.onus.Range(func(key interface{}, value interface{}) bool {
2331 dh.onus.Delete(key)
2332 return true
2333 })
2334
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002335 /*Delete discovered ONU map for the device*/
2336 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2337 dh.discOnus.Delete(key)
2338 return true
2339 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002340 if len(errs) > 0 {
2341 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2342 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2343 }
2344 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002345}
2346
Mahir Gunyela2e68702022-12-07 00:00:42 -08002347// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002348func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002349 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302350 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002351 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002352 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002353 return nil
2354}
2355
David K. Bainbridge794735f2020-02-11 21:01:37 -08002356func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002357 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002358 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002359 "packet-indication": *packetIn,
2360 "device-id": dh.device.Id,
2361 "packet": hex.EncodeToString(packetIn.Pkt),
2362 })
2363 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002364 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2365 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2366 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002367 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002368 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002369 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002370 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002371 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002372 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002373 "logical-port-num": logicalPortNum,
2374 "device-id": dh.device.Id,
2375 "packet": hex.EncodeToString(packetIn.Pkt),
2376 })
2377 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002378
khenaidoodc2116e2021-10-19 17:33:19 -04002379 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002380 DeviceId: dh.device.Id,
2381 Port: logicalPortNum,
2382 Packet: packetIn.Pkt,
2383 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302384 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002385 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302386 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002387 "device-id": dh.device.Id,
2388 "packet": hex.EncodeToString(packetIn.Pkt),
2389 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002390 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391
Matteo Scandolo92186242020-06-12 10:54:18 -07002392 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002393 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002394 "packet": hex.EncodeToString(packetIn.Pkt),
2395 "device-id": dh.device.Id,
2396 })
2397 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002398 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002399}
2400
Mahir Gunyela2e68702022-12-07 00:00:42 -08002401// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2402func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2403 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2404 if err != nil {
2405 return olterrors.NewErrInvalidValue(log.Fields{
2406 "egress-nni-port": egressPortNo,
2407 "device-id": dh.device.Id,
2408 }, err)
2409 }
2410 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2411
2412 if logger.V(log.DebugLevel) {
2413 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2414 "uplink-pkt": uplinkPkt,
2415 "packet": hex.EncodeToString(packet.Data),
2416 "device-id": dh.device.Id,
2417 })
2418 }
2419
2420 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2421 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2422 "packet": hex.EncodeToString(packet.Data),
2423 "device-id": dh.device.Id,
2424 }, err)
2425 }
2426 return nil
2427}
2428
2429// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2430func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2431 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2432 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2433 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2434 // Do not packet-out lldp packets on uni port.
2435 // ONOS has no clue about uni/nni ports, it just packets out on all
2436 // available ports on the Logical Switch. It should not be interested
2437 // in the UNI links.
2438 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2439 "device-id": dh.device.Id,
2440 })
2441 return nil
2442 }
2443 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2444 if innerEthType == 0x8100 {
2445 // q-in-q 802.1ad or 802.1q double tagged packet.
2446 // slice out the outer tag.
2447 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2448 if logger.V(log.DebugLevel) {
2449 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2450 "packet-data": hex.EncodeToString(packet.Data),
2451 "device-id": dh.device.Id,
2452 })
2453 }
2454 }
2455 }
2456 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2457 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2458 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2459 var gemPortID uint32
2460 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2461 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2462 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2463 }
2464 if err != nil {
2465 // In this case the openolt agent will receive the gemPortID as 0.
2466 // The agent tries to retrieve the gemPortID in this case.
2467 // This may not always succeed at the agent and packetOut may fail.
2468 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2469 "intf-id": intfID,
2470 "onu-id": onuID,
2471 "uni-id": uniID,
2472 "packet": hex.EncodeToString(packet.Data),
2473 "device-id": dh.device.Id,
2474 "error": err,
2475 })
2476 }
2477
2478 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2479 if logger.V(log.DebugLevel) {
2480 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2481 "egress-port-no": egressPortNo,
2482 "intf-id": intfID,
2483 "onu-id": onuID,
2484 "uni-id": uniID,
2485 "gem-port-id": gemPortID,
2486 "packet": hex.EncodeToString(packet.Data),
2487 "device-id": dh.device.Id,
2488 })
2489 }
2490
2491 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2492 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2493 "source": "adapter",
2494 "destination": "onu",
2495 "egress-port-number": egressPortNo,
2496 "intf-id": intfID,
2497 "oni-id": onuID,
2498 "uni-id": uniID,
2499 "gem-port-id": gemPortID,
2500 "packet": hex.EncodeToString(packet.Data),
2501 "device-id": dh.device.Id,
2502 }, err)
2503 }
2504 return nil
2505}
2506
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002507// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002508func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002509 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002510 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002511 "device-id": dh.device.Id,
2512 "egress-port-no": egressPortNo,
2513 "pkt-length": len(packet.Data),
2514 "packet": hex.EncodeToString(packet.Data),
2515 })
2516 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002517
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002518 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002519 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002520 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002521 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002522 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002523 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002524 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002525 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302526 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002527 "egressPortType": egressPortType,
2528 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302529 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002530 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002531 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002532 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002533}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002534
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002535func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2536 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002537}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302538
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002539func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002540
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002541 defer func() {
2542 dh.lockDevice.Lock()
2543 dh.isHeartbeatCheckActive = false
2544 dh.lockDevice.Unlock()
2545 }()
2546
2547 dh.lockDevice.Lock()
2548 dh.isHeartbeatCheckActive = true
2549 dh.lockDevice.Unlock()
2550
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302551 // start the heartbeat check towards the OLT.
2552 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302553 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302554
2555 for {
2556 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2557 select {
2558 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002559 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002560 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002561 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302562 if timerCheck == nil {
2563 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002564 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302565 }
2566 } else {
2567 if timerCheck != nil {
2568 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002569 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302570 }
2571 timerCheck = nil
2572 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302573 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2574 if dh.heartbeatSignature == 0 {
2575 // First time the signature will be 0, update the signture to DB when not found.
2576 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2577 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2578 }
2579 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2580
2581 dh.lockDevice.RLock()
2582 // Stop the read indication only if it the routine is active
2583 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2584 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2585 // on next execution of the readIndication routine.
2586 if !dh.isReadIndicationRoutineActive {
2587 // Start reading indications
2588 go func() {
2589 if err = dh.readIndications(ctx); err != nil {
2590 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2591 }
2592 }()
2593 }
2594 dh.lockDevice.RUnlock()
2595
2596 } else {
2597 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2598 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2599 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2600 go dh.updateStateRebooted(ctx)
2601 }
2602
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302603 }
2604 cancel()
2605 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002606 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302607 return
2608 }
2609 }
2610}
2611
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002612func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002613 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002614 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002615 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2616 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2617 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2618 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2619 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002620 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002621 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2622 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002623 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302624
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302625 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002626 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002627 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002628 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002629 DeviceId: dh.device.Id,
2630 OperStatus: voltha.OperStatus_UNKNOWN,
2631 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2632 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002633 _ = 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 -04002634 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302635 /*
2636 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2637 DeviceId: dh.device.Id,
2638 PortTypeFilter: 0,
2639 OperStatus: voltha.OperStatus_UNKNOWN,
2640 }); err != nil {
2641 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2642 }
2643 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002644
2645 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002646 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002647 cloned := proto.Clone(device).(*voltha.Device)
2648 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2649 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2650 dh.device = cloned // update local copy of the device
2651 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002652
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002653 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002654 // Stop the Stats collector
2655 if dh.isCollectorActive {
2656 dh.stopCollector <- true
2657 }
2658 // stop the heartbeat check routine
2659 if dh.isHeartbeatCheckActive {
2660 dh.stopHeartbeatCheck <- true
2661 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002662 // Stop the read indication only if it the routine is active
2663 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2664 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2665 // on next execution of the readIndication routine.
2666 if dh.isReadIndicationRoutineActive {
2667 dh.stopIndications <- true
2668 }
2669 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002670 dh.transitionMap.Handle(ctx, DeviceInit)
2671
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302672 }
2673}
kesavand39e0aa32020-01-28 20:58:50 -05002674
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302675func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2676 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2677 if err != nil || device == nil {
2678 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2679 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2680 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2681 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2682 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2683 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2684 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2685 return
2686 }
2687
2688 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2689 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2690 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2691 DeviceId: dh.device.Id,
2692 OperStatus: voltha.OperStatus_REBOOTED,
2693 ConnStatus: voltha.ConnectStatus_REACHABLE,
2694 }); err != nil {
2695 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2696 }
2697
2698 dh.lockDevice.RLock()
2699 // Stop the read indication only if it the routine is active
2700 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2701 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2702 // on next execution of the readIndication routine.
2703 if dh.isReadIndicationRoutineActive {
2704 dh.stopIndications <- true
2705 }
2706 dh.lockDevice.RUnlock()
2707
2708 //raise olt communication failure event
2709 raisedTs := time.Now().Unix()
2710 cloned := proto.Clone(device).(*voltha.Device)
2711 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2712 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2713 dh.device = cloned // update local copy of the device
2714 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2715
Gustavo Silva41af9122022-10-11 11:05:13 -03002716 if err := dh.cleanupDeviceResources(ctx); err != nil {
2717 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
2718 } else {
2719 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2720 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002721
2722 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302723 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002724 if dh.isCollectorActive {
2725 dh.stopCollector <- true
2726 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302727 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002728 if dh.isHeartbeatCheckActive {
2729 dh.stopHeartbeatCheck <- true
2730 }
2731 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302732
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002733 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302734
2735 //reset adapter reconcile flag
2736 dh.adapterPreviouslyConnected = false
2737 for {
2738
2739 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2740 if err != nil || childDevices == nil {
2741 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2742 continue
2743 }
2744 if len(childDevices.Items) == 0 {
2745 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
2746 break
2747 } else {
2748 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
2749 time.Sleep(5 * time.Second)
2750 }
2751
2752 }
2753 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
2754 dh.transitionMap.Handle(ctx, DeviceInit)
2755
2756}
2757
kesavand39e0aa32020-01-28 20:58:50 -05002758// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002759func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2760 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2761 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002762}
2763
2764// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002765func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2766 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2767 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002768}
2769
Mahir Gunyela2e68702022-12-07 00:00:42 -08002770// 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 +00002771func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2772 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002773 if port.GetType() == voltha.Port_ETHERNET_NNI {
2774 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002775 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302776 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302777 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002778 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002779 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002780 }
2781 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002782 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002783 ponIntf := &oop.Interface{IntfId: ponID}
2784 var operStatus voltha.OperStatus_Types
2785 if enablePort {
2786 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302787 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002788
2789 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302790 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002791 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002792 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002793 }
2794 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002795 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002796 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002797 } else {
2798 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302799 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002800 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302801 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002802 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002803 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002804 }
2805 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002806 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002807 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002808 }
khenaidoodc2116e2021-10-19 17:33:19 -04002809 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002810 DeviceId: dh.device.Id,
2811 PortType: voltha.Port_PON_OLT,
2812 PortNo: port.PortNo,
2813 OperStatus: operStatus,
2814 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302815 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302816 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002817 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002818 }
2819 return nil
2820}
2821
Mahir Gunyela2e68702022-12-07 00:00:42 -08002822// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002823func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002824 // Disable the port and update the oper_port_status to core
2825 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002826 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002827 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002828 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302829 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302830 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002831 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002832 }
2833 }
2834 }
2835 return nil
2836}
2837
Mahir Gunyela2e68702022-12-07 00:00:42 -08002838// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002839func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2840 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2841 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002842 if port.Type == voltha.Port_ETHERNET_NNI {
2843 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002844 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002845 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002846 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002847 }
2848 }
2849 if port.Type == voltha.Port_PON_OLT {
2850 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002851 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002852 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002853 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002854 }
2855 }
2856 }
2857}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002858
2859// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002860func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002861 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07002862 if dh.getDeviceDeletionInProgressFlag() {
2863 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
2864 // will reboot, so everything will be reset on the pOLT too.
2865 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
2866 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
2867 return nil
2868 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002869 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002870 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002871
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002872 var sn *oop.SerialNumber
2873 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002874 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302875 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002876 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302877 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002878 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002879 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002880
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002881 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002882 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00002883 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002884 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2885 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2886 "device-id": dh.device.Id,
2887 "intf-id": intfID,
2888 "onuID": onuID,
2889 "err": err})
2890 } else {
2891 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00002892 // Delete flows from device before schedulers and queue
2893 // Clear flowids for gem cache.
2894 removedFlows := []uint64{}
2895 for _, gem := range onuGem.GemPorts {
2896 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
2897 for _, flowID := range flowIDs {
2898 //multiple gem port can have the same flow id
2899 //it is better to send only one flowRemove request to the agent
2900 var alreadyRemoved bool
2901 for _, removedFlowID := range removedFlows {
2902 if removedFlowID == flowID {
2903 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
2904 alreadyRemoved = true
2905 break
2906 }
2907 }
2908 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002909 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00002910 removedFlows = appendUnique64bit(removedFlows, flowID)
2911 }
2912 }
2913 }
2914 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
2915 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002916 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2917 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2918 "device-id": dh.device.Id,
2919 "onu-device": onu,
2920 "err": err})
2921 }
yasin saplibddc2d72022-02-08 13:10:17 +00002922 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002923 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2924 "intf-id": intfID,
2925 "onu-device": onu,
2926 "onu-gem": onuGem,
2927 "err": err})
2928 //Not returning error on cleanup.
2929 }
2930 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302931
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002932 }
yasin saplibddc2d72022-02-08 13:10:17 +00002933 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002934 dh.onus.Delete(onuKey)
2935 dh.discOnus.Delete(onuSn)
2936
2937 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002938 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302939 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302940 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002941 "onu-id": onuID}, err).Log()
2942 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002943
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002944 return nil
2945}
Mahir Gunyela2e68702022-12-07 00:00:42 -08002946func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
2947 flow := &oop.Flow{FlowId: flowID}
2948 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2949 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
2950 "device-id": dh.device.Id})
2951 } else {
2952 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
2953 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
2954 "device-id": dh.device.Id,
2955 "err": err})
2956 }
2957 }
2958}
Girish Gowdracefae192020-03-19 18:14:10 -07002959
2960func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002961 for _, field := range flow_utils.GetOfbFields(flow) {
2962 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002963 return field.GetPort()
2964 }
2965 }
2966 return InvalidPort
2967}
2968
2969func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002970 for _, action := range flow_utils.GetActions(flow) {
2971 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002972 if out := action.GetOutput(); out != nil {
2973 return out.GetPort()
2974 }
2975 }
2976 }
2977 return InvalidPort
2978}
2979
Girish Gowdracefae192020-03-19 18:14:10 -07002980func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2981 inPort := getInPortFromFlow(flow)
2982 outPort := getOutPortFromFlow(flow)
2983
2984 if inPort == InvalidPort || outPort == InvalidPort {
2985 return inPort, outPort
2986 }
2987
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002988 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002989 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002990 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002991 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002992 return uniPort, outPort
2993 }
2994 }
2995 } else {
2996 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002997 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002998 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002999 return inPort, uniPort
3000 }
3001 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003002 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003003 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003004 return uniPort, outPort
3005 }
3006 }
3007 }
3008
3009 return InvalidPort, InvalidPort
3010}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003011
3012func extractOmciTransactionID(omciPkt []byte) uint16 {
3013 if len(omciPkt) > 3 {
3014 d := omciPkt[0:2]
3015 transid := binary.BigEndian.Uint16(d)
3016 return transid
3017 }
3018 return 0
3019}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003020
3021// StoreOnuDevice stores the onu parameters to the local cache.
3022func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3023 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3024 dh.onus.Store(onuKey, onuDevice)
3025}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003026
khenaidoodc2116e2021-10-19 17:33:19 -04003027func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003028 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003029 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003030 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003031 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003032 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003033 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003034 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003035 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3036 return nil, err
3037 }
3038 ID = device.ProxyAddress.GetOnuId()
3039 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3040 valueparam.Onu = &Onu
3041 valueparam.Value = value
3042
3043 // This API is unsupported until agent patch is added
3044 resp.Unsupported = uint32(value)
3045 _ = ctx
3046
3047 // Uncomment this code once agent changes are complete and tests
3048 /*
3049 resp, err = dh.Client.GetValue(ctx, valueparam)
3050 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003051 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003052 return nil, err
3053 }
3054 */
3055
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003056 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 -08003057 return resp, nil
3058}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003059
yasin saplid0566272021-12-21 09:10:30 +00003060func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
3061 // Default to NNI
3062 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003063 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003064 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003065 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003066 }
3067 return intfID
3068}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003069
Mahir Gunyelb0046752021-02-26 13:51:05 -08003070func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
3071 dh.perPonOnuIndicationChannelLock.Lock()
3072 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3073 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003074 return ch.indicationChannel
3075 }
3076 channels := onuIndicationChannels{
3077 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08003078 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003079 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003080 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003081 stopChannel: make(chan struct{}),
3082 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003083 dh.perPonOnuIndicationChannel[intfID] = channels
3084 dh.perPonOnuIndicationChannelLock.Unlock()
3085 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003086 return channels.indicationChannel
3087
3088}
3089
Mahir Gunyelb0046752021-02-26 13:51:05 -08003090func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3091 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3092 dh.perPonOnuIndicationChannelLock.Lock()
3093 defer dh.perPonOnuIndicationChannelLock.Unlock()
3094 for _, v := range dh.perPonOnuIndicationChannel {
3095 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003096 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003097 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003098}
3099
Mahir Gunyelb0046752021-02-26 13:51:05 -08003100func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3101 ind := onuIndicationMsg{
3102 ctx: ctx,
3103 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003104 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003105 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003106 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003107 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003108}
3109
Mahir Gunyelb0046752021-02-26 13:51:05 -08003110func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003111 for {
3112 select {
3113 // process one indication per onu, before proceeding to the next one
3114 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003115 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003116 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003117 "ind": indication})
3118 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003119 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003120 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003121 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3122 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003123 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003124 }
3125 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003126 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003127 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3128 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003129 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003130 }
3131 }
3132 case <-onuChannels.stopChannel:
3133 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3134 close(onuChannels.indicationChannel)
3135 return
3136 }
3137 }
3138}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003139
3140// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3141// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003142func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003143 if dh.getDeviceDeletionInProgressFlag() {
3144 // The device itself is going to be reset as part of deletion. So nothing to be done.
3145 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3146 return nil
3147 }
3148
Girish Gowdra491a9c62021-01-06 16:43:07 -08003149 // Step1 : Fill McastFlowOrGroupControlBlock
3150 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3151 // Step3 : Wait on response channel for response
3152 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003153 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003154 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3155 errChan := make(chan error)
3156 var groupID uint32
3157 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3158 ctx: ctx,
3159 flowOrGroupAction: action,
3160 flow: flow,
3161 group: group,
3162 errChan: &errChan,
3163 }
3164 if flow != nil {
3165 groupID = flow_utils.GetGroup(flow)
3166 } else if group != nil {
3167 groupID = group.Desc.GroupId
3168 } else {
3169 return errors.New("flow-and-group-both-nil")
3170 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003171 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3172 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3173 // Derive the appropriate go routine to handle the request by a simple module operation.
3174 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3175 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3176 // Wait for handler to return error value
3177 err := <-errChan
3178 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3179 return err
3180 }
3181 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3182 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003183}
3184
3185// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003186func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003187 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003188 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003189 // block on the channel to receive an incoming mcast flow/group
3190 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003191 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3192 if mcastFlowOrGroupCb.flow != nil {
3193 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3194 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3195 log.Fields{"device-id": dh.device.Id,
3196 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003197 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3198 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3199 for _, flMgr := range dh.flowMgr {
3200 if flMgr != nil {
3201 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3202 break
3203 }
3204 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003205 // Pass the return value over the return channel
3206 *mcastFlowOrGroupCb.errChan <- err
3207 } else { // flow remove
3208 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3209 log.Fields{"device-id": dh.device.Id,
3210 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003211 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3212 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3213 for _, flMgr := range dh.flowMgr {
3214 if flMgr != nil {
3215 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3216 break
3217 }
3218 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003219 // Pass the return value over the return channel
3220 *mcastFlowOrGroupCb.errChan <- err
3221 }
3222 } else { // mcast group
3223 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3224 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3225 log.Fields{"device-id": dh.device.Id,
3226 "groupToAdd": mcastFlowOrGroupCb.group})
3227 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3228 // Pass the return value over the return channel
3229 *mcastFlowOrGroupCb.errChan <- err
3230 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3231 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3232 log.Fields{"device-id": dh.device.Id,
3233 "groupToModify": mcastFlowOrGroupCb.group})
3234 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3235 // Pass the return value over the return channel
3236 *mcastFlowOrGroupCb.errChan <- err
3237 } else { // group remove
3238 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3239 log.Fields{"device-id": dh.device.Id,
3240 "groupToRemove": mcastFlowOrGroupCb.group})
3241 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3242 // Pass the return value over the return channel
3243 *mcastFlowOrGroupCb.errChan <- err
3244 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003245 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003246 case <-stopHandler:
3247 dh.mcastHandlerRoutineActive[routineIndex] = false
3248 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003249 }
3250 }
3251}
kesavand62126212021-01-12 04:56:06 -05003252
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003253// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003254func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003255 for i, v := range dh.stopMcastHandlerRoutine {
3256 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003257 select {
3258 case v <- true:
3259 case <-time.After(time.Second * 5):
3260 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3261 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003262 }
3263 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003264
3265 if dh.incomingMcastFlowOrGroup != nil {
3266 for k := range dh.incomingMcastFlowOrGroup {
3267 if dh.incomingMcastFlowOrGroup[k] != nil {
3268 dh.incomingMcastFlowOrGroup[k] = nil
3269 }
3270 }
3271 dh.incomingMcastFlowOrGroup = nil
3272 }
3273
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003274 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003275 logger.Debug(ctx, "stopped all mcast handler routines")
3276}
3277
kesavand62126212021-01-12 04:56:06 -05003278func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3279
3280 singleValResp := extension.SingleGetValueResponse{
3281 Response: &extension.GetValueResponse{
3282 Response: &extension.GetValueResponse_PortCoutners{
3283 PortCoutners: &extension.GetOltPortCountersResponse{},
3284 },
3285 },
3286 }
3287
3288 errResp := func(status extension.GetValueResponse_Status,
3289 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3290 return &extension.SingleGetValueResponse{
3291 Response: &extension.GetValueResponse{
3292 Status: status,
3293 ErrReason: reason,
3294 },
3295 }
3296 }
3297
3298 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3299 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3300 //send error response
3301 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3302 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3303 }
3304 statIndChn := make(chan bool, 1)
3305 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3306 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3307 //request openOlt agent to send the the port statistics indication
3308
3309 go func() {
3310 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3311 if err != nil {
3312 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3313 }
3314 }()
3315 select {
3316 case <-statIndChn:
3317 //indication received for ports stats
3318 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3319 case <-time.After(oltPortInfoTimeout * time.Second):
3320 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3321 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3322 case <-ctx.Done():
3323 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3324 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3325 }
3326 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3327 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003328 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003329 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3330 cmnni := dh.portStats.collectNNIMetrics(intfID)
3331 if cmnni == nil {
3332 //TODO define the error reason
3333 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3334 }
3335 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3336 return &singleValResp
3337
3338 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3339 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003340 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003341 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3342 cmpon := dh.portStats.collectPONMetrics(intfID)
3343 if cmpon == nil {
3344 //TODO define the error reason
3345 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3346 }
3347 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3348 return &singleValResp
3349 }
3350 }
3351 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3352}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303353
3354func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3355
3356 singleValResp := extension.SingleGetValueResponse{
3357 Response: &extension.GetValueResponse{
3358 Response: &extension.GetValueResponse_OnuPonCounters{
3359 OnuPonCounters: &extension.GetOnuCountersResponse{},
3360 },
3361 },
3362 }
3363
3364 errResp := func(status extension.GetValueResponse_Status,
3365 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3366 return &extension.SingleGetValueResponse{
3367 Response: &extension.GetValueResponse{
3368 Status: status,
3369 ErrReason: reason,
3370 },
3371 }
3372 }
3373 intfID := onuPonInfo.IntfId
3374 onuID := onuPonInfo.OnuId
3375 onuKey := dh.formOnuKey(intfID, onuID)
3376
3377 if _, ok := dh.onus.Load(onuKey); !ok {
3378 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3379 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3380 }
3381 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3382 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3383 if cmnni == nil {
3384 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3385 }
3386 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3387 return &singleValResp
3388
3389}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003390
3391func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3392
3393 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3394 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3395 if err != nil {
3396 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3397 return generateSingleGetValueErrorResponse(err)
3398 }
3399 return &extension.SingleGetValueResponse{
3400 Response: &extension.GetValueResponse{
3401 Status: extension.GetValueResponse_OK,
3402 Response: &extension.GetValueResponse_RxPower{
3403 RxPower: &extension.GetRxPowerResponse{
3404 IntfId: rxPowerRequest.IntfId,
3405 OnuId: rxPowerRequest.OnuId,
3406 Status: rxPower.Status,
3407 FailReason: rxPower.FailReason.String(),
3408 RxPower: rxPower.RxPowerMeanDbm,
3409 },
3410 },
3411 },
3412 }
3413}
3414
3415func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3416 errResp := func(status extension.GetValueResponse_Status,
3417 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3418 return &extension.SingleGetValueResponse{
3419 Response: &extension.GetValueResponse{
3420 Status: status,
3421 ErrReason: reason,
3422 },
3423 }
3424 }
3425
3426 if err != nil {
3427 if e, ok := status.FromError(err); ok {
3428 switch e.Code() {
3429 case codes.Internal:
3430 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3431 case codes.DeadlineExceeded:
3432 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3433 case codes.Unimplemented:
3434 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3435 case codes.NotFound:
3436 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3437 }
3438 }
3439 }
3440
3441 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3442}
khenaidoo106c61a2021-08-11 18:05:46 -04003443
3444/*
3445Helper functions to communicate with Core
3446*/
3447
3448func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3449 cClient, err := dh.coreClient.GetCoreServiceClient()
3450 if err != nil || cClient == nil {
3451 return nil, err
3452 }
3453 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3454 defer cancel()
3455 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3456}
3457
khenaidoodc2116e2021-10-19 17:33:19 -04003458func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003459 cClient, err := dh.coreClient.GetCoreServiceClient()
3460 if err != nil || cClient == nil {
3461 return nil, err
3462 }
3463 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3464 defer cancel()
3465 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3466}
3467
khenaidoodc2116e2021-10-19 17:33:19 -04003468func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003469 cClient, err := dh.coreClient.GetCoreServiceClient()
3470 if err != nil || cClient == nil {
3471 return err
3472 }
3473 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3474 defer cancel()
3475 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3476 return err
3477}
3478
3479func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3480 cClient, err := dh.coreClient.GetCoreServiceClient()
3481 if err != nil || cClient == nil {
3482 return nil, err
3483 }
3484 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3485 defer cancel()
3486 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3487}
3488
3489func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3490 cClient, err := dh.coreClient.GetCoreServiceClient()
3491 if err != nil || cClient == nil {
3492 return nil, err
3493 }
3494 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3495 defer cancel()
3496 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3497}
3498
3499func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3500 cClient, err := dh.coreClient.GetCoreServiceClient()
3501 if err != nil || cClient == nil {
3502 return err
3503 }
3504 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3505 defer cancel()
3506 _, err = cClient.DeviceUpdate(subCtx, device)
3507 return err
3508}
3509
khenaidoodc2116e2021-10-19 17:33:19 -04003510func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003511 cClient, err := dh.coreClient.GetCoreServiceClient()
3512 if err != nil || cClient == nil {
3513 return nil, err
3514 }
3515 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3516 defer cancel()
3517 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3518}
3519
khenaidoodc2116e2021-10-19 17:33:19 -04003520func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003521 cClient, err := dh.coreClient.GetCoreServiceClient()
3522 if err != nil || cClient == nil {
3523 return err
3524 }
3525 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3526 defer cancel()
3527 _, err = cClient.SendPacketIn(subCtx, pkt)
3528 return err
3529}
3530
3531func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3532 cClient, err := dh.coreClient.GetCoreServiceClient()
3533 if err != nil || cClient == nil {
3534 return err
3535 }
3536 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3537 defer cancel()
3538 _, err = cClient.PortCreated(subCtx, port)
3539 return err
3540}
3541
khenaidoodc2116e2021-10-19 17:33:19 -04003542func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003543 cClient, err := dh.coreClient.GetCoreServiceClient()
3544 if err != nil || cClient == nil {
3545 return err
3546 }
3547 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3548 defer cancel()
3549 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3550 return err
3551}
3552
khenaidoodc2116e2021-10-19 17:33:19 -04003553func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003554 cClient, err := dh.coreClient.GetCoreServiceClient()
3555 if err != nil || cClient == nil {
3556 return err
3557 }
3558 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3559 defer cancel()
3560 _, err = cClient.PortStateUpdate(subCtx, portState)
3561 return err
3562}
3563
khenaidoodc2116e2021-10-19 17:33:19 -04003564func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003565 cClient, err := dh.coreClient.GetCoreServiceClient()
3566 if err != nil || cClient == nil {
3567 return nil, err
3568 }
3569 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3570 defer cancel()
3571 return cClient.GetDevicePort(subCtx, portFilter)
3572}
3573
3574/*
3575Helper functions to communicate with child adapter
3576*/
3577
khenaidoodc2116e2021-10-19 17:33:19 -04003578func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003579 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3580 if err != nil || aClient == nil {
3581 return err
3582 }
3583 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3584 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3585 defer cancel()
3586 _, err = aClient.OmciIndication(subCtx, response)
3587 return err
3588}
3589
khenaidoodc2116e2021-10-19 17:33:19 -04003590func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003591 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3592 if err != nil || aClient == nil {
3593 return err
3594 }
3595 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3596 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3597 defer cancel()
3598 _, err = aClient.OnuIndication(subCtx, onuInd)
3599 return err
3600}
3601
khenaidoodc2116e2021-10-19 17:33:19 -04003602func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003603 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3604 if err != nil || aClient == nil {
3605 return err
3606 }
3607 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3608 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3609 defer cancel()
3610 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3611 return err
3612}
3613
khenaidoodc2116e2021-10-19 17:33:19 -04003614func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003615 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3616 if err != nil || aClient == nil {
3617 return err
3618 }
3619 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3620 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3621 defer cancel()
3622 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3623 return err
3624}
3625
khenaidoodc2116e2021-10-19 17:33:19 -04003626func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003627 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3628 if err != nil || aClient == nil {
3629 return err
3630 }
3631 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3632 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3633 defer cancel()
3634 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3635 return err
3636}
3637
3638/*
3639Helper functions for remote communication
3640*/
3641
3642// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3643// supports is deleted
3644func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3645 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3646
3647 dh.lockChildAdapterClients.Lock()
3648 defer dh.lockChildAdapterClients.Unlock()
3649 if _, ok := dh.childAdapterClients[endpoint]; ok {
3650 // Already set
3651 return nil
3652 }
3653
3654 // Setup child's adapter grpc connection
3655 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003656 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3657 dh.cfg.AdapterEndpoint,
3658 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05003659 "onu_inter_adapter_service.OnuInterAdapterService",
3660 dh.onuInterAdapterRestarted,
3661 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003662 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3663 return err
3664 }
khenaidooefff76e2021-12-15 16:51:30 -05003665 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003666
3667 // Wait until we have a connection to the child adapter.
3668 // Unlimited retries or until context expires
3669 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3670 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3671 for {
3672 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3673 if err == nil && client != nil {
3674 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3675 break
3676 }
3677 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3678 // Backoff
3679 if err = backoff.Backoff(subCtx); err != nil {
3680 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3681 break
3682 }
3683 }
3684 return nil
3685}
3686
khenaidoodc2116e2021-10-19 17:33:19 -04003687func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003688
3689 // First check from cache
3690 dh.lockChildAdapterClients.RLock()
3691 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3692 dh.lockChildAdapterClients.RUnlock()
3693 return cgClient.GetOnuInterAdapterServiceClient()
3694 }
3695 dh.lockChildAdapterClients.RUnlock()
3696
3697 // Set the child connection - can occur on restarts
3698 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3699 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3700 cancel()
3701 if err != nil {
3702 return nil, err
3703 }
3704
3705 // Get the child client now
3706 dh.lockChildAdapterClients.RLock()
3707 defer dh.lockChildAdapterClients.RUnlock()
3708 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3709 return cgClient.GetOnuInterAdapterServiceClient()
3710 }
3711 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3712}
3713
3714func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3715 dh.lockChildAdapterClients.Lock()
3716 defer dh.lockChildAdapterClients.Unlock()
3717 for key, client := range dh.childAdapterClients {
3718 client.Stop(ctx)
3719 delete(dh.childAdapterClients, key)
3720 }
3721}
3722
khenaidooefff76e2021-12-15 16:51:30 -05003723// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
3724func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
3725 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003726 return nil
3727}
3728
khenaidooefff76e2021-12-15 16:51:30 -05003729// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
3730func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
3731 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003732 return nil
3733 }
khenaidooefff76e2021-12-15 16:51:30 -05003734 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04003735}
Girish Gowdra950326e2021-11-05 12:43:24 -07003736
3737func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3738 dh.lockDevice.Lock()
3739 defer dh.lockDevice.Unlock()
3740 dh.isDeviceDeletionInProgress = flag
3741}
3742
3743func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3744 dh.lockDevice.RLock()
3745 defer dh.lockDevice.RUnlock()
3746 return dh.isDeviceDeletionInProgress
3747}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003748
3749// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3750// Returns false if waiting timed out.
3751func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3752 c := make(chan struct{})
3753 go func() {
3754 defer close(c)
3755 wg.Wait()
3756 }()
3757 select {
3758 case <-c:
3759 return true // completed normally
3760 case <-time.After(timeout):
3761 return false // timed out
3762 }
3763}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303764
3765func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
3766 val, err := json.Marshal(signature)
3767 if err != nil {
3768 logger.Error(ctx, "failed-to-marshal")
3769 return
3770 }
3771 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
3772 logger.Error(ctx, "failed-to-store-hearbeat-signature")
3773 }
3774}
3775
3776func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
3777 var signature uint32
3778
3779 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
3780 if er == nil {
3781 if Value != nil {
3782 Val, er := kvstore.ToByte(Value.Value)
3783 if er != nil {
3784 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
3785 return signature
3786 }
3787 if er = json.Unmarshal(Val, &signature); er != nil {
3788 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
3789 return signature
3790 }
3791 }
3792 }
3793 return signature
3794}