blob: 610f3e3fb8b00074988e4fcc59f80ca667909144 [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 {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302126 if dh.Client != nil {
2127 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2128 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2129 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2130 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302131 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302132 } else {
2133 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2134
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302135 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302136
Neha Sharma96b7bf22020-06-15 10:37:32 +00002137 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002138
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002139 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002140 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002141 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002142 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002143 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2144 } else {
2145 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2146 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2147 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002148 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002149 if retError == nil {
2150 //Update the device oper status as ACTIVE
2151 device.OperStatus = voltha.OperStatus_ACTIVE
2152 } else {
2153 //Update the device oper status as FAILED
2154 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002155 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002156 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002157
khenaidoodc2116e2021-10-19 17:33:19 -04002158 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002159 DeviceId: device.Id,
2160 OperStatus: device.OperStatus,
2161 ConnStatus: device.ConnectStatus,
2162 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302163 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002164 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002165 "connect-status": device.ConnectStatus,
2166 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002167 }
kesavand39e0aa32020-01-28 20:58:50 -05002168
Neha Sharma96b7bf22020-06-15 10:37:32 +00002169 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002170
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002171 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002172}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002173
npujarec5762e2020-01-01 14:08:48 +05302174func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002175 var uniID uint32
2176 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002177 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302178 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002179 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002180 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002181 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002182 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2183 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2184 } else {
2185 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2186 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002187 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002188 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002189 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002190 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002191 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002192 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002193 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002194 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002195 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002196 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002198 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002199 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002200 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002201 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002202 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302203 }
yasin saplibddc2d72022-02-08 13:10:17 +00002204 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2205 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002206 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002207 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302208 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002209 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002210 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002211 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 -03002212 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002213 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002214 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002215 if len(errs) > 0 {
2216 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2217 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2218 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002219 return nil
2220}
2221
Devmalya Paul495b94a2019-08-27 19:42:00 -04002222// 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 +05302223func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002224 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002225 /* Clear the KV store data associated with the all the UNI ports
2226 This clears up flow data and also resource map data for various
2227 other pon resources like alloc_id and gemport_id
2228 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002229
2230 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002231
2232 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002233
Gustavo Silva41af9122022-10-11 11:05:13 -03002234 err := dh.cleanupDeviceResources(ctx)
2235 if err != nil {
2236 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2237 } else {
2238 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2239 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002240
Himani Chawla49a5d562020-11-25 11:53:44 +05302241 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002242 // Stop the Stats collector
2243 if dh.isCollectorActive {
2244 dh.stopCollector <- true
2245 }
2246 // stop the heartbeat check routine
2247 if dh.isHeartbeatCheckActive {
2248 dh.stopHeartbeatCheck <- true
2249 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302250 // Stop the read indication only if it the routine is active
2251 if dh.isReadIndicationRoutineActive {
2252 dh.stopIndications <- true
2253 }
2254 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002255 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002256 //Reset the state
2257 if dh.Client != nil {
2258 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002259 go func() {
2260 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
2261 if err = dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err != nil {
2262 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
2263 }
2264 }()
2265 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002266 }
2267 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002268 // There is no need to update the core about operation status and connection status of the OLT.
2269 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2270 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2271 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002272
khenaidoo7eb2d672021-10-22 19:08:50 -04002273 // Stop the adapter grpc clients for that parent device
2274 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002275 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002276}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002277
2278// StopAllFlowRoutines stops all flow routines
2279func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2280 var wg sync.WaitGroup
2281 wg.Add(1) // for the mcast routine below to finish
2282 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2283 for _, flMgr := range dh.flowMgr {
2284 if flMgr != nil {
2285 wg.Add(1) // for the flow handler routine below to finish
2286 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2287 }
2288 }
2289 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2290 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2291 } else {
2292 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2293 }
2294}
2295
Gustavo Silva41af9122022-10-11 11:05:13 -03002296func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2297 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002298 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302299 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002300 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002301 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002302 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002303 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002304 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2305 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302306 }
2307 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002308 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2309 errs = append(errs, err)
2310 }
2311 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2312 errs = append(errs, err)
2313 }
2314 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2315 errs = append(errs, err)
2316 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002317 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002318 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002319 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002320 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002321 }
2322 // Clean up NNI manager's data
2323 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2324 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002325 }
A R Karthick1f85b802019-10-11 05:06:05 +00002326
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002327 dh.CloseKVClient(ctx)
2328
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002329 // Take one final sweep at cleaning up KV store for the OLT device
2330 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002331 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2332 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002333 }
2334
Devmalya Paul495b94a2019-08-27 19:42:00 -04002335 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302336 dh.onus.Range(func(key interface{}, value interface{}) bool {
2337 dh.onus.Delete(key)
2338 return true
2339 })
2340
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002341 /*Delete discovered ONU map for the device*/
2342 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2343 dh.discOnus.Delete(key)
2344 return true
2345 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002346 if len(errs) > 0 {
2347 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2348 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2349 }
2350 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002351}
2352
Mahir Gunyela2e68702022-12-07 00:00:42 -08002353// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302355 if dh.Client != nil {
2356 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2357 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2358 }
2359 } else {
2360 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2361
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002362 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302363
Neha Sharma96b7bf22020-06-15 10:37:32 +00002364 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002365 return nil
2366}
2367
David K. Bainbridge794735f2020-02-11 21:01:37 -08002368func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002369 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002370 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002371 "packet-indication": *packetIn,
2372 "device-id": dh.device.Id,
2373 "packet": hex.EncodeToString(packetIn.Pkt),
2374 })
2375 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002376 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2377 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2378 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002379 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002380 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002381 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002382 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002383 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002385 "logical-port-num": logicalPortNum,
2386 "device-id": dh.device.Id,
2387 "packet": hex.EncodeToString(packetIn.Pkt),
2388 })
2389 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002390
khenaidoodc2116e2021-10-19 17:33:19 -04002391 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002392 DeviceId: dh.device.Id,
2393 Port: logicalPortNum,
2394 Packet: packetIn.Pkt,
2395 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302396 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002397 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302398 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002399 "device-id": dh.device.Id,
2400 "packet": hex.EncodeToString(packetIn.Pkt),
2401 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002402 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002403
Matteo Scandolo92186242020-06-12 10:54:18 -07002404 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002405 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002406 "packet": hex.EncodeToString(packetIn.Pkt),
2407 "device-id": dh.device.Id,
2408 })
2409 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002410 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002411}
2412
Mahir Gunyela2e68702022-12-07 00:00:42 -08002413// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2414func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2415 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2416 if err != nil {
2417 return olterrors.NewErrInvalidValue(log.Fields{
2418 "egress-nni-port": egressPortNo,
2419 "device-id": dh.device.Id,
2420 }, err)
2421 }
2422 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2423
2424 if logger.V(log.DebugLevel) {
2425 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2426 "uplink-pkt": uplinkPkt,
2427 "packet": hex.EncodeToString(packet.Data),
2428 "device-id": dh.device.Id,
2429 })
2430 }
2431
2432 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2433 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2434 "packet": hex.EncodeToString(packet.Data),
2435 "device-id": dh.device.Id,
2436 }, err)
2437 }
2438 return nil
2439}
2440
2441// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2442func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2443 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2444 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2445 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2446 // Do not packet-out lldp packets on uni port.
2447 // ONOS has no clue about uni/nni ports, it just packets out on all
2448 // available ports on the Logical Switch. It should not be interested
2449 // in the UNI links.
2450 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2451 "device-id": dh.device.Id,
2452 })
2453 return nil
2454 }
2455 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2456 if innerEthType == 0x8100 {
2457 // q-in-q 802.1ad or 802.1q double tagged packet.
2458 // slice out the outer tag.
2459 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2460 if logger.V(log.DebugLevel) {
2461 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2462 "packet-data": hex.EncodeToString(packet.Data),
2463 "device-id": dh.device.Id,
2464 })
2465 }
2466 }
2467 }
2468 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2469 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2470 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2471 var gemPortID uint32
2472 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2473 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2474 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2475 }
2476 if err != nil {
2477 // In this case the openolt agent will receive the gemPortID as 0.
2478 // The agent tries to retrieve the gemPortID in this case.
2479 // This may not always succeed at the agent and packetOut may fail.
2480 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2481 "intf-id": intfID,
2482 "onu-id": onuID,
2483 "uni-id": uniID,
2484 "packet": hex.EncodeToString(packet.Data),
2485 "device-id": dh.device.Id,
2486 "error": err,
2487 })
2488 }
2489
2490 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2491 if logger.V(log.DebugLevel) {
2492 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2493 "egress-port-no": egressPortNo,
2494 "intf-id": intfID,
2495 "onu-id": onuID,
2496 "uni-id": uniID,
2497 "gem-port-id": gemPortID,
2498 "packet": hex.EncodeToString(packet.Data),
2499 "device-id": dh.device.Id,
2500 })
2501 }
2502
2503 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2504 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2505 "source": "adapter",
2506 "destination": "onu",
2507 "egress-port-number": egressPortNo,
2508 "intf-id": intfID,
2509 "oni-id": onuID,
2510 "uni-id": uniID,
2511 "gem-port-id": gemPortID,
2512 "packet": hex.EncodeToString(packet.Data),
2513 "device-id": dh.device.Id,
2514 }, err)
2515 }
2516 return nil
2517}
2518
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002519// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002520func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002521 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002522 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002523 "device-id": dh.device.Id,
2524 "egress-port-no": egressPortNo,
2525 "pkt-length": len(packet.Data),
2526 "packet": hex.EncodeToString(packet.Data),
2527 })
2528 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002529
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002530 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002531 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002532 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002533 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002534 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002535 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002536 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002537 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302538 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002539 "egressPortType": egressPortType,
2540 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302541 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002542 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002543 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002544 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002545}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002546
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002547func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2548 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002549}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302550
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002551func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002552
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002553 defer func() {
2554 dh.lockDevice.Lock()
2555 dh.isHeartbeatCheckActive = false
2556 dh.lockDevice.Unlock()
2557 }()
2558
2559 dh.lockDevice.Lock()
2560 dh.isHeartbeatCheckActive = true
2561 dh.lockDevice.Unlock()
2562
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302563 // start the heartbeat check towards the OLT.
2564 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302565 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302566
2567 for {
2568 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2569 select {
2570 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002571 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002572 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002573 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302574 if timerCheck == nil {
2575 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002576 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302577 }
2578 } else {
2579 if timerCheck != nil {
2580 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002581 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302582 }
2583 timerCheck = nil
2584 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302585 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2586 if dh.heartbeatSignature == 0 {
2587 // First time the signature will be 0, update the signture to DB when not found.
2588 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2589 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2590 }
2591 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2592
2593 dh.lockDevice.RLock()
2594 // Stop the read indication only if it the routine is active
2595 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2596 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2597 // on next execution of the readIndication routine.
2598 if !dh.isReadIndicationRoutineActive {
2599 // Start reading indications
2600 go func() {
2601 if err = dh.readIndications(ctx); err != nil {
2602 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2603 }
2604 }()
2605 }
2606 dh.lockDevice.RUnlock()
2607
2608 } else {
2609 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2610 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2611 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2612 go dh.updateStateRebooted(ctx)
2613 }
2614
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302615 }
2616 cancel()
2617 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002618 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302619 return
2620 }
2621 }
2622}
2623
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002624func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002625 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002626 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002627 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2628 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2629 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2630 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2631 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002632 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002633 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2634 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002635 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302636
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302637 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002638 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002639 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002640 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002641 DeviceId: dh.device.Id,
2642 OperStatus: voltha.OperStatus_UNKNOWN,
2643 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2644 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002645 _ = 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 -04002646 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302647 /*
2648 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2649 DeviceId: dh.device.Id,
2650 PortTypeFilter: 0,
2651 OperStatus: voltha.OperStatus_UNKNOWN,
2652 }); err != nil {
2653 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2654 }
2655 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002656
2657 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002658 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002659 cloned := proto.Clone(device).(*voltha.Device)
2660 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2661 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2662 dh.device = cloned // update local copy of the device
2663 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002664
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002665 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002666 // Stop the Stats collector
2667 if dh.isCollectorActive {
2668 dh.stopCollector <- true
2669 }
2670 // stop the heartbeat check routine
2671 if dh.isHeartbeatCheckActive {
2672 dh.stopHeartbeatCheck <- true
2673 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002674 // Stop the read indication only if it the routine is active
2675 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2676 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2677 // on next execution of the readIndication routine.
2678 if dh.isReadIndicationRoutineActive {
2679 dh.stopIndications <- true
2680 }
2681 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002682 dh.transitionMap.Handle(ctx, DeviceInit)
2683
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302684 }
2685}
kesavand39e0aa32020-01-28 20:58:50 -05002686
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302687func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2688 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2689 if err != nil || device == nil {
2690 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2691 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2692 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2693 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2694 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2695 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2696 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2697 return
2698 }
2699
2700 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2701 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2702 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2703 DeviceId: dh.device.Id,
2704 OperStatus: voltha.OperStatus_REBOOTED,
2705 ConnStatus: voltha.ConnectStatus_REACHABLE,
2706 }); err != nil {
2707 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2708 }
2709
2710 dh.lockDevice.RLock()
2711 // Stop the read indication only if it the routine is active
2712 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2713 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2714 // on next execution of the readIndication routine.
2715 if dh.isReadIndicationRoutineActive {
2716 dh.stopIndications <- true
2717 }
2718 dh.lockDevice.RUnlock()
2719
2720 //raise olt communication failure event
2721 raisedTs := time.Now().Unix()
2722 cloned := proto.Clone(device).(*voltha.Device)
2723 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2724 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2725 dh.device = cloned // update local copy of the device
2726 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2727
Gustavo Silva41af9122022-10-11 11:05:13 -03002728 if err := dh.cleanupDeviceResources(ctx); err != nil {
2729 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
2730 } else {
2731 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2732 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002733
2734 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302735 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002736 if dh.isCollectorActive {
2737 dh.stopCollector <- true
2738 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302739 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002740 if dh.isHeartbeatCheckActive {
2741 dh.stopHeartbeatCheck <- true
2742 }
2743 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302744
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002745 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302746
2747 //reset adapter reconcile flag
2748 dh.adapterPreviouslyConnected = false
2749 for {
2750
2751 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2752 if err != nil || childDevices == nil {
2753 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2754 continue
2755 }
2756 if len(childDevices.Items) == 0 {
2757 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
2758 break
2759 } else {
2760 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
2761 time.Sleep(5 * time.Second)
2762 }
2763
2764 }
2765 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
2766 dh.transitionMap.Handle(ctx, DeviceInit)
2767
2768}
2769
kesavand39e0aa32020-01-28 20:58:50 -05002770// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002771func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2772 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2773 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002774}
2775
2776// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002777func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2778 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2779 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002780}
2781
Mahir Gunyela2e68702022-12-07 00:00:42 -08002782// 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 +00002783func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2784 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002785 if port.GetType() == voltha.Port_ETHERNET_NNI {
2786 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002787 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302788 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302789 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002790 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002791 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002792 }
2793 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002794 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002795 ponIntf := &oop.Interface{IntfId: ponID}
2796 var operStatus voltha.OperStatus_Types
2797 if enablePort {
2798 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302799 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002800
2801 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302802 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002803 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002804 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002805 }
2806 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002807 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002808 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002809 } else {
2810 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302811 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002812 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302813 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002814 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002815 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002816 }
2817 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002818 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002819 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002820 }
khenaidoodc2116e2021-10-19 17:33:19 -04002821 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002822 DeviceId: dh.device.Id,
2823 PortType: voltha.Port_PON_OLT,
2824 PortNo: port.PortNo,
2825 OperStatus: operStatus,
2826 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302827 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302828 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002829 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002830 }
2831 return nil
2832}
2833
Mahir Gunyela2e68702022-12-07 00:00:42 -08002834// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002835func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002836 // Disable the port and update the oper_port_status to core
2837 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002838 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002839 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002840 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302841 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302842 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002843 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002844 }
2845 }
2846 }
2847 return nil
2848}
2849
Mahir Gunyela2e68702022-12-07 00:00:42 -08002850// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002851func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2852 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2853 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002854 if port.Type == voltha.Port_ETHERNET_NNI {
2855 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002856 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002857 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002858 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002859 }
2860 }
2861 if port.Type == voltha.Port_PON_OLT {
2862 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002863 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002864 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002865 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002866 }
2867 }
2868 }
2869}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002870
2871// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002872func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002873 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07002874 if dh.getDeviceDeletionInProgressFlag() {
2875 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
2876 // will reboot, so everything will be reset on the pOLT too.
2877 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
2878 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
2879 return nil
2880 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002881 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002882 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002883
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002884 var sn *oop.SerialNumber
2885 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002886 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302887 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002888 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302889 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002890 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002891 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002892
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002893 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002894 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00002895 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002896 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2897 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2898 "device-id": dh.device.Id,
2899 "intf-id": intfID,
2900 "onuID": onuID,
2901 "err": err})
2902 } else {
2903 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00002904 // Delete flows from device before schedulers and queue
2905 // Clear flowids for gem cache.
2906 removedFlows := []uint64{}
2907 for _, gem := range onuGem.GemPorts {
2908 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
2909 for _, flowID := range flowIDs {
2910 //multiple gem port can have the same flow id
2911 //it is better to send only one flowRemove request to the agent
2912 var alreadyRemoved bool
2913 for _, removedFlowID := range removedFlows {
2914 if removedFlowID == flowID {
2915 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
2916 alreadyRemoved = true
2917 break
2918 }
2919 }
2920 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002921 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00002922 removedFlows = appendUnique64bit(removedFlows, flowID)
2923 }
2924 }
2925 }
2926 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
2927 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002928 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2929 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2930 "device-id": dh.device.Id,
2931 "onu-device": onu,
2932 "err": err})
2933 }
yasin saplibddc2d72022-02-08 13:10:17 +00002934 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002935 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2936 "intf-id": intfID,
2937 "onu-device": onu,
2938 "onu-gem": onuGem,
2939 "err": err})
2940 //Not returning error on cleanup.
2941 }
2942 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302943
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002944 }
yasin saplibddc2d72022-02-08 13:10:17 +00002945 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002946 dh.onus.Delete(onuKey)
2947 dh.discOnus.Delete(onuSn)
2948
2949 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002950 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302951 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302952 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002953 "onu-id": onuID}, err).Log()
2954 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002955
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002956 return nil
2957}
Mahir Gunyela2e68702022-12-07 00:00:42 -08002958func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
2959 flow := &oop.Flow{FlowId: flowID}
2960 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2961 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
2962 "device-id": dh.device.Id})
2963 } else {
2964 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
2965 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
2966 "device-id": dh.device.Id,
2967 "err": err})
2968 }
2969 }
2970}
Girish Gowdracefae192020-03-19 18:14:10 -07002971
2972func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002973 for _, field := range flow_utils.GetOfbFields(flow) {
2974 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002975 return field.GetPort()
2976 }
2977 }
2978 return InvalidPort
2979}
2980
2981func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002982 for _, action := range flow_utils.GetActions(flow) {
2983 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002984 if out := action.GetOutput(); out != nil {
2985 return out.GetPort()
2986 }
2987 }
2988 }
2989 return InvalidPort
2990}
2991
Girish Gowdracefae192020-03-19 18:14:10 -07002992func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2993 inPort := getInPortFromFlow(flow)
2994 outPort := getOutPortFromFlow(flow)
2995
2996 if inPort == InvalidPort || outPort == InvalidPort {
2997 return inPort, outPort
2998 }
2999
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003000 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003001 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003002 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 } else {
3008 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003009 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003010 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003011 return inPort, uniPort
3012 }
3013 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003014 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003015 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003016 return uniPort, outPort
3017 }
3018 }
3019 }
3020
3021 return InvalidPort, InvalidPort
3022}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003023
3024func extractOmciTransactionID(omciPkt []byte) uint16 {
3025 if len(omciPkt) > 3 {
3026 d := omciPkt[0:2]
3027 transid := binary.BigEndian.Uint16(d)
3028 return transid
3029 }
3030 return 0
3031}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003032
3033// StoreOnuDevice stores the onu parameters to the local cache.
3034func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3035 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3036 dh.onus.Store(onuKey, onuDevice)
3037}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003038
khenaidoodc2116e2021-10-19 17:33:19 -04003039func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003040 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003041 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003042 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003043 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003044 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003045 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003046 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003047 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3048 return nil, err
3049 }
3050 ID = device.ProxyAddress.GetOnuId()
3051 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3052 valueparam.Onu = &Onu
3053 valueparam.Value = value
3054
3055 // This API is unsupported until agent patch is added
3056 resp.Unsupported = uint32(value)
3057 _ = ctx
3058
3059 // Uncomment this code once agent changes are complete and tests
3060 /*
3061 resp, err = dh.Client.GetValue(ctx, valueparam)
3062 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003063 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003064 return nil, err
3065 }
3066 */
3067
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003068 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 -08003069 return resp, nil
3070}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003071
yasin saplid0566272021-12-21 09:10:30 +00003072func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
3073 // Default to NNI
3074 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003075 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003076 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003077 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003078 }
3079 return intfID
3080}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003081
Mahir Gunyelb0046752021-02-26 13:51:05 -08003082func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
3083 dh.perPonOnuIndicationChannelLock.Lock()
3084 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3085 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003086 return ch.indicationChannel
3087 }
3088 channels := onuIndicationChannels{
3089 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08003090 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003091 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003092 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003093 stopChannel: make(chan struct{}),
3094 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003095 dh.perPonOnuIndicationChannel[intfID] = channels
3096 dh.perPonOnuIndicationChannelLock.Unlock()
3097 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003098 return channels.indicationChannel
3099
3100}
3101
Mahir Gunyelb0046752021-02-26 13:51:05 -08003102func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3103 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3104 dh.perPonOnuIndicationChannelLock.Lock()
3105 defer dh.perPonOnuIndicationChannelLock.Unlock()
3106 for _, v := range dh.perPonOnuIndicationChannel {
3107 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003108 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003109 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003110}
3111
Mahir Gunyelb0046752021-02-26 13:51:05 -08003112func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3113 ind := onuIndicationMsg{
3114 ctx: ctx,
3115 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003116 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003117 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003118 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003119 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003120}
3121
Mahir Gunyelb0046752021-02-26 13:51:05 -08003122func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003123 for {
3124 select {
3125 // process one indication per onu, before proceeding to the next one
3126 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003127 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003128 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003129 "ind": indication})
3130 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003131 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003132 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003133 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3134 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003135 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003136 }
3137 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003138 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003139 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3140 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003141 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003142 }
3143 }
3144 case <-onuChannels.stopChannel:
3145 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3146 close(onuChannels.indicationChannel)
3147 return
3148 }
3149 }
3150}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003151
3152// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3153// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003154func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003155 if dh.getDeviceDeletionInProgressFlag() {
3156 // The device itself is going to be reset as part of deletion. So nothing to be done.
3157 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3158 return nil
3159 }
3160
Girish Gowdra491a9c62021-01-06 16:43:07 -08003161 // Step1 : Fill McastFlowOrGroupControlBlock
3162 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3163 // Step3 : Wait on response channel for response
3164 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003165 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003166 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3167 errChan := make(chan error)
3168 var groupID uint32
3169 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3170 ctx: ctx,
3171 flowOrGroupAction: action,
3172 flow: flow,
3173 group: group,
3174 errChan: &errChan,
3175 }
3176 if flow != nil {
3177 groupID = flow_utils.GetGroup(flow)
3178 } else if group != nil {
3179 groupID = group.Desc.GroupId
3180 } else {
3181 return errors.New("flow-and-group-both-nil")
3182 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003183 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3184 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3185 // Derive the appropriate go routine to handle the request by a simple module operation.
3186 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3187 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3188 // Wait for handler to return error value
3189 err := <-errChan
3190 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3191 return err
3192 }
3193 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3194 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003195}
3196
3197// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003198func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003199 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003200 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003201 // block on the channel to receive an incoming mcast flow/group
3202 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003203 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3204 if mcastFlowOrGroupCb.flow != nil {
3205 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3206 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3207 log.Fields{"device-id": dh.device.Id,
3208 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003209 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3210 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3211 for _, flMgr := range dh.flowMgr {
3212 if flMgr != nil {
3213 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3214 break
3215 }
3216 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003217 // Pass the return value over the return channel
3218 *mcastFlowOrGroupCb.errChan <- err
3219 } else { // flow remove
3220 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3221 log.Fields{"device-id": dh.device.Id,
3222 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003223 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3224 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3225 for _, flMgr := range dh.flowMgr {
3226 if flMgr != nil {
3227 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3228 break
3229 }
3230 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003231 // Pass the return value over the return channel
3232 *mcastFlowOrGroupCb.errChan <- err
3233 }
3234 } else { // mcast group
3235 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3236 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3237 log.Fields{"device-id": dh.device.Id,
3238 "groupToAdd": mcastFlowOrGroupCb.group})
3239 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3240 // Pass the return value over the return channel
3241 *mcastFlowOrGroupCb.errChan <- err
3242 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3243 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3244 log.Fields{"device-id": dh.device.Id,
3245 "groupToModify": mcastFlowOrGroupCb.group})
3246 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3247 // Pass the return value over the return channel
3248 *mcastFlowOrGroupCb.errChan <- err
3249 } else { // group remove
3250 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3251 log.Fields{"device-id": dh.device.Id,
3252 "groupToRemove": mcastFlowOrGroupCb.group})
3253 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3254 // Pass the return value over the return channel
3255 *mcastFlowOrGroupCb.errChan <- err
3256 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003257 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003258 case <-stopHandler:
3259 dh.mcastHandlerRoutineActive[routineIndex] = false
3260 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003261 }
3262 }
3263}
kesavand62126212021-01-12 04:56:06 -05003264
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003265// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003266func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003267 for i, v := range dh.stopMcastHandlerRoutine {
3268 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003269 select {
3270 case v <- true:
3271 case <-time.After(time.Second * 5):
3272 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3273 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003274 }
3275 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003276
3277 if dh.incomingMcastFlowOrGroup != nil {
3278 for k := range dh.incomingMcastFlowOrGroup {
3279 if dh.incomingMcastFlowOrGroup[k] != nil {
3280 dh.incomingMcastFlowOrGroup[k] = nil
3281 }
3282 }
3283 dh.incomingMcastFlowOrGroup = nil
3284 }
3285
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003286 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003287 logger.Debug(ctx, "stopped all mcast handler routines")
3288}
3289
kesavand62126212021-01-12 04:56:06 -05003290func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3291
3292 singleValResp := extension.SingleGetValueResponse{
3293 Response: &extension.GetValueResponse{
3294 Response: &extension.GetValueResponse_PortCoutners{
3295 PortCoutners: &extension.GetOltPortCountersResponse{},
3296 },
3297 },
3298 }
3299
3300 errResp := func(status extension.GetValueResponse_Status,
3301 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3302 return &extension.SingleGetValueResponse{
3303 Response: &extension.GetValueResponse{
3304 Status: status,
3305 ErrReason: reason,
3306 },
3307 }
3308 }
3309
3310 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3311 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3312 //send error response
3313 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3314 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3315 }
3316 statIndChn := make(chan bool, 1)
3317 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3318 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3319 //request openOlt agent to send the the port statistics indication
3320
3321 go func() {
3322 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3323 if err != nil {
3324 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3325 }
3326 }()
3327 select {
3328 case <-statIndChn:
3329 //indication received for ports stats
3330 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3331 case <-time.After(oltPortInfoTimeout * time.Second):
3332 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3333 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3334 case <-ctx.Done():
3335 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3336 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3337 }
3338 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3339 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003340 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003341 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3342 cmnni := dh.portStats.collectNNIMetrics(intfID)
3343 if cmnni == nil {
3344 //TODO define the error reason
3345 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3346 }
3347 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3348 return &singleValResp
3349
3350 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3351 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003352 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003353 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3354 cmpon := dh.portStats.collectPONMetrics(intfID)
3355 if cmpon == nil {
3356 //TODO define the error reason
3357 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3358 }
3359 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3360 return &singleValResp
3361 }
3362 }
3363 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3364}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303365
3366func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3367
3368 singleValResp := extension.SingleGetValueResponse{
3369 Response: &extension.GetValueResponse{
3370 Response: &extension.GetValueResponse_OnuPonCounters{
3371 OnuPonCounters: &extension.GetOnuCountersResponse{},
3372 },
3373 },
3374 }
3375
3376 errResp := func(status extension.GetValueResponse_Status,
3377 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3378 return &extension.SingleGetValueResponse{
3379 Response: &extension.GetValueResponse{
3380 Status: status,
3381 ErrReason: reason,
3382 },
3383 }
3384 }
3385 intfID := onuPonInfo.IntfId
3386 onuID := onuPonInfo.OnuId
3387 onuKey := dh.formOnuKey(intfID, onuID)
3388
3389 if _, ok := dh.onus.Load(onuKey); !ok {
3390 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3391 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3392 }
3393 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3394 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3395 if cmnni == nil {
3396 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3397 }
3398 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3399 return &singleValResp
3400
3401}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003402
3403func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3404
3405 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3406 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3407 if err != nil {
3408 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3409 return generateSingleGetValueErrorResponse(err)
3410 }
3411 return &extension.SingleGetValueResponse{
3412 Response: &extension.GetValueResponse{
3413 Status: extension.GetValueResponse_OK,
3414 Response: &extension.GetValueResponse_RxPower{
3415 RxPower: &extension.GetRxPowerResponse{
3416 IntfId: rxPowerRequest.IntfId,
3417 OnuId: rxPowerRequest.OnuId,
3418 Status: rxPower.Status,
3419 FailReason: rxPower.FailReason.String(),
3420 RxPower: rxPower.RxPowerMeanDbm,
3421 },
3422 },
3423 },
3424 }
3425}
3426
3427func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3428 errResp := func(status extension.GetValueResponse_Status,
3429 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3430 return &extension.SingleGetValueResponse{
3431 Response: &extension.GetValueResponse{
3432 Status: status,
3433 ErrReason: reason,
3434 },
3435 }
3436 }
3437
3438 if err != nil {
3439 if e, ok := status.FromError(err); ok {
3440 switch e.Code() {
3441 case codes.Internal:
3442 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3443 case codes.DeadlineExceeded:
3444 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3445 case codes.Unimplemented:
3446 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3447 case codes.NotFound:
3448 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3449 }
3450 }
3451 }
3452
3453 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3454}
khenaidoo106c61a2021-08-11 18:05:46 -04003455
3456/*
3457Helper functions to communicate with Core
3458*/
3459
3460func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3461 cClient, err := dh.coreClient.GetCoreServiceClient()
3462 if err != nil || cClient == nil {
3463 return nil, err
3464 }
3465 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3466 defer cancel()
3467 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3468}
3469
khenaidoodc2116e2021-10-19 17:33:19 -04003470func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003471 cClient, err := dh.coreClient.GetCoreServiceClient()
3472 if err != nil || cClient == nil {
3473 return nil, err
3474 }
3475 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3476 defer cancel()
3477 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3478}
3479
khenaidoodc2116e2021-10-19 17:33:19 -04003480func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003481 cClient, err := dh.coreClient.GetCoreServiceClient()
3482 if err != nil || cClient == nil {
3483 return err
3484 }
3485 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3486 defer cancel()
3487 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3488 return err
3489}
3490
3491func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3492 cClient, err := dh.coreClient.GetCoreServiceClient()
3493 if err != nil || cClient == nil {
3494 return nil, err
3495 }
3496 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3497 defer cancel()
3498 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3499}
3500
3501func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3502 cClient, err := dh.coreClient.GetCoreServiceClient()
3503 if err != nil || cClient == nil {
3504 return nil, err
3505 }
3506 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3507 defer cancel()
3508 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3509}
3510
3511func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3512 cClient, err := dh.coreClient.GetCoreServiceClient()
3513 if err != nil || cClient == nil {
3514 return err
3515 }
3516 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3517 defer cancel()
3518 _, err = cClient.DeviceUpdate(subCtx, device)
3519 return err
3520}
3521
khenaidoodc2116e2021-10-19 17:33:19 -04003522func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003523 cClient, err := dh.coreClient.GetCoreServiceClient()
3524 if err != nil || cClient == nil {
3525 return nil, err
3526 }
3527 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3528 defer cancel()
3529 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3530}
3531
khenaidoodc2116e2021-10-19 17:33:19 -04003532func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003533 cClient, err := dh.coreClient.GetCoreServiceClient()
3534 if err != nil || cClient == nil {
3535 return err
3536 }
3537 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3538 defer cancel()
3539 _, err = cClient.SendPacketIn(subCtx, pkt)
3540 return err
3541}
3542
3543func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3544 cClient, err := dh.coreClient.GetCoreServiceClient()
3545 if err != nil || cClient == nil {
3546 return err
3547 }
3548 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3549 defer cancel()
3550 _, err = cClient.PortCreated(subCtx, port)
3551 return err
3552}
3553
khenaidoodc2116e2021-10-19 17:33:19 -04003554func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003555 cClient, err := dh.coreClient.GetCoreServiceClient()
3556 if err != nil || cClient == nil {
3557 return err
3558 }
3559 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3560 defer cancel()
3561 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3562 return err
3563}
3564
khenaidoodc2116e2021-10-19 17:33:19 -04003565func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003566 cClient, err := dh.coreClient.GetCoreServiceClient()
3567 if err != nil || cClient == nil {
3568 return err
3569 }
3570 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3571 defer cancel()
3572 _, err = cClient.PortStateUpdate(subCtx, portState)
3573 return err
3574}
3575
khenaidoodc2116e2021-10-19 17:33:19 -04003576func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003577 cClient, err := dh.coreClient.GetCoreServiceClient()
3578 if err != nil || cClient == nil {
3579 return nil, err
3580 }
3581 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3582 defer cancel()
3583 return cClient.GetDevicePort(subCtx, portFilter)
3584}
3585
3586/*
3587Helper functions to communicate with child adapter
3588*/
3589
khenaidoodc2116e2021-10-19 17:33:19 -04003590func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) 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-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3596 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3597 defer cancel()
3598 _, err = aClient.OmciIndication(subCtx, response)
3599 return err
3600}
3601
khenaidoodc2116e2021-10-19 17:33:19 -04003602func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) 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-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3608 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3609 defer cancel()
3610 _, err = aClient.OnuIndication(subCtx, onuInd)
3611 return err
3612}
3613
khenaidoodc2116e2021-10-19 17:33:19 -04003614func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) 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-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3620 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3621 defer cancel()
3622 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3623 return err
3624}
3625
khenaidoodc2116e2021-10-19 17:33:19 -04003626func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) 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-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3632 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3633 defer cancel()
3634 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3635 return err
3636}
3637
khenaidoodc2116e2021-10-19 17:33:19 -04003638func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003639 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3640 if err != nil || aClient == nil {
3641 return err
3642 }
3643 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3644 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3645 defer cancel()
3646 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3647 return err
3648}
3649
3650/*
3651Helper functions for remote communication
3652*/
3653
3654// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3655// supports is deleted
3656func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3657 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3658
3659 dh.lockChildAdapterClients.Lock()
3660 defer dh.lockChildAdapterClients.Unlock()
3661 if _, ok := dh.childAdapterClients[endpoint]; ok {
3662 // Already set
3663 return nil
3664 }
3665
3666 // Setup child's adapter grpc connection
3667 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003668 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3669 dh.cfg.AdapterEndpoint,
3670 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05003671 "onu_inter_adapter_service.OnuInterAdapterService",
3672 dh.onuInterAdapterRestarted,
3673 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003674 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3675 return err
3676 }
khenaidooefff76e2021-12-15 16:51:30 -05003677 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003678
3679 // Wait until we have a connection to the child adapter.
3680 // Unlimited retries or until context expires
3681 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3682 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3683 for {
3684 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3685 if err == nil && client != nil {
3686 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3687 break
3688 }
3689 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3690 // Backoff
3691 if err = backoff.Backoff(subCtx); err != nil {
3692 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3693 break
3694 }
3695 }
3696 return nil
3697}
3698
khenaidoodc2116e2021-10-19 17:33:19 -04003699func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003700
3701 // First check from cache
3702 dh.lockChildAdapterClients.RLock()
3703 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3704 dh.lockChildAdapterClients.RUnlock()
3705 return cgClient.GetOnuInterAdapterServiceClient()
3706 }
3707 dh.lockChildAdapterClients.RUnlock()
3708
3709 // Set the child connection - can occur on restarts
3710 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3711 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3712 cancel()
3713 if err != nil {
3714 return nil, err
3715 }
3716
3717 // Get the child client now
3718 dh.lockChildAdapterClients.RLock()
3719 defer dh.lockChildAdapterClients.RUnlock()
3720 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3721 return cgClient.GetOnuInterAdapterServiceClient()
3722 }
3723 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3724}
3725
3726func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3727 dh.lockChildAdapterClients.Lock()
3728 defer dh.lockChildAdapterClients.Unlock()
3729 for key, client := range dh.childAdapterClients {
3730 client.Stop(ctx)
3731 delete(dh.childAdapterClients, key)
3732 }
3733}
3734
khenaidooefff76e2021-12-15 16:51:30 -05003735// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
3736func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
3737 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003738 return nil
3739}
3740
khenaidooefff76e2021-12-15 16:51:30 -05003741// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
3742func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
3743 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003744 return nil
3745 }
khenaidooefff76e2021-12-15 16:51:30 -05003746 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04003747}
Girish Gowdra950326e2021-11-05 12:43:24 -07003748
3749func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3750 dh.lockDevice.Lock()
3751 defer dh.lockDevice.Unlock()
3752 dh.isDeviceDeletionInProgress = flag
3753}
3754
3755func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3756 dh.lockDevice.RLock()
3757 defer dh.lockDevice.RUnlock()
3758 return dh.isDeviceDeletionInProgress
3759}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003760
3761// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3762// Returns false if waiting timed out.
3763func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3764 c := make(chan struct{})
3765 go func() {
3766 defer close(c)
3767 wg.Wait()
3768 }()
3769 select {
3770 case <-c:
3771 return true // completed normally
3772 case <-time.After(timeout):
3773 return false // timed out
3774 }
3775}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303776
3777func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
3778 val, err := json.Marshal(signature)
3779 if err != nil {
3780 logger.Error(ctx, "failed-to-marshal")
3781 return
3782 }
3783 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
3784 logger.Error(ctx, "failed-to-store-hearbeat-signature")
3785 }
3786}
3787
3788func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
3789 var signature uint32
3790
3791 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
3792 if er == nil {
3793 if Value != nil {
3794 Val, er := kvstore.ToByte(Value.Value)
3795 if er != nil {
3796 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
3797 return signature
3798 }
3799 if er = json.Unmarshal(Val, &signature); er != nil {
3800 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
3801 return signature
3802 }
3803 }
3804 }
3805 return signature
3806}