blob: dadd31653ec002135f8c5d33400e3c70e8700561 [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
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530216 kvStoreDevicePath := fmt.Sprintf(dh.cm.Backend.PathPrefix, "/%s/", dh.device.Id)
217 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, kvStoreDevicePath)
218 if dh.kvStore == nil {
219 logger.Error(ctx, "Failed to setup KV store")
220 return nil
221 }
222
Girish Gowdra491a9c62021-01-06 16:43:07 -0800223 // Create a slice of buffered channels for handling concurrent mcast flow/group.
224 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700225 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
226 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800227 for i := range dh.incomingMcastFlowOrGroup {
228 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800229 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800230 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
231 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
232 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
233 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700234 dh.mcastHandlerRoutineActive[i] = true
235 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800236 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700237 //TODO initialize the support classes.
238 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530239}
240
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530241func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
242 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
243 switch storeType {
244 case "etcd":
245 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
246 }
247 return nil, errors.New("unsupported-kv-store")
248}
249
250// SetKVClient sets the KV client and return a kv backend
251func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
252 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
253 if err != nil {
254 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
255 return nil
256 }
257
258 kvbackend := &db.Backend{
259 Client: kvClient,
260 StoreType: backend,
261 Address: addr,
262 Timeout: rsrcMgr.KvstoreTimeout,
263 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
264
265 return kvbackend
266}
267
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000268// CloseKVClient closes open KV clients
269func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
270 if dh.resourceMgr != nil {
271 for _, rscMgr := range dh.resourceMgr {
272 if rscMgr != nil {
273 rscMgr.CloseKVClient(ctx)
274 }
275 }
276 }
277 if dh.flowMgr != nil {
278 for _, flMgr := range dh.flowMgr {
279 if flMgr != nil {
280 flMgr.CloseKVClient(ctx)
281 }
282 }
283 }
284}
285
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530286// start save the device to the data model
287func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700288 dh.lockDevice.Lock()
289 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000290 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700291 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000292 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530293}
294
khenaidooefff76e2021-12-15 16:51:30 -0500295// Stop stops the device handler
296func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700297 dh.lockDevice.Lock()
298 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000299 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500300 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400301
khenaidooefff76e2021-12-15 16:51:30 -0500302 // Delete (which will stop also) all grpc connections to the child adapters
303 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000304 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530305}
306
ssiddiqui04386ee2021-08-23 21:58:25 +0530307func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
308 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
309 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
310 if pooledIntfID == intfID {
311 return resourceRanges.GetTechnology()
312 }
313 }
314 }
315 return ""
316}
317
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400318func macifyIP(ip net.IP) string {
319 if len(ip) > 0 {
320 oct1 := strconv.FormatInt(int64(ip[12]), 16)
321 oct2 := strconv.FormatInt(int64(ip[13]), 16)
322 oct3 := strconv.FormatInt(int64(ip[14]), 16)
323 oct4 := strconv.FormatInt(int64(ip[15]), 16)
324 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
325 }
326 return ""
327}
328
Neha Sharma96b7bf22020-06-15 10:37:32 +0000329func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400330 var genmac string
331 var addr net.IP
332 var ips []string
333 var err error
334
Neha Sharma96b7bf22020-06-15 10:37:32 +0000335 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400336
337 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000338 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400339
340 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000341 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400342 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000343 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400344 }
345 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000346 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530347 log.Fields{"host": ips[0],
348 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400349 return genmac, nil
350 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000351 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400352 }
353
354 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530356 log.Fields{"host": host,
357 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400358 return genmac, nil
359}
360
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530361func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700362 slist := strings.Split(mac, ":")
363 result := make([]uint32, len(slist))
364 var err error
365 var tmp int64
366 for index, val := range slist {
367 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
368 return []uint32{1, 2, 3, 4, 5, 6}
369 }
370 result[index] = uint32(tmp)
371 }
372 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530373}
374
Mahir Gunyela2e68702022-12-07 00:00:42 -0800375// GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800376func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530377
David K. Bainbridge794735f2020-02-11 21:01:37 -0800378 switch portType {
379 case voltha.Port_ETHERNET_NNI:
380 return fmt.Sprintf("nni-%d", portNum), nil
381 case voltha.Port_PON_OLT:
382 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700383 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800384
Girish Kumarf26e4882020-03-05 06:49:10 +0000385 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530386}
387
Elia Battiston596406d2022-02-02 12:19:00 +0100388func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
389 if speedMbps == 0 {
390 //In case it was not set in the indication
391 //and no other value was provided
392 speedMbps = defaultPortSpeedMbps
393 }
394
395 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
396 switch speedMbps {
397 case 1000000:
398 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
399 case 100000:
400 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
401 case 40000:
402 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
403 case 10000:
404 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
405 case 1000:
406 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
407 case 100:
408 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
409 case 10:
410 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
411 }
412
413 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
414
415 port := &of.OfpPort{
416 HwAddr: macAddressToUint32Array(macAddress),
417 Config: 0,
418 State: uint32(of.OfpPortState_OFPPS_LIVE),
419 Curr: capacity,
420 Advertised: capacity,
421 Peer: capacity,
422 CurrSpeed: speedMbps * 1000, //kbps
423 MaxSpeed: speedMbps * 1000, //kbps
424 }
425
426 return port
427}
428
429func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000430 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700431 if state == "up" {
432 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500433 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500434 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700435 } else {
436 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500437 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700438 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700439 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400440 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800441 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000442 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400443 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500444
khenaidoo106c61a2021-08-11 18:05:46 -0400445 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400446 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400447 DeviceId: dh.device.Id,
448 Port: portNum,
449 })
450 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000451 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400452 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400453 DeviceId: dh.device.Id,
454 PortType: portType,
455 PortNo: portNum,
456 OperStatus: operStatus})
457 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400458 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
459 "device-id": dh.device.Id,
460 "port-type": portType,
461 "port-number": portNum,
462 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500463 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400464 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500465 }
khenaidoo106c61a2021-08-11 18:05:46 -0400466
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400467 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400468 port = &voltha.Port{
469 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700470 PortNo: portNum,
471 Label: label,
472 Type: portType,
473 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100474 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700475 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000476 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700477 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400478 err = dh.createPortInCore(ctx, port)
479 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000480 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000482 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400483 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000484 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530485 return nil
486}
487
Kent Hagermane6ff1012020-07-14 15:07:53 -0400488func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400489 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530490 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400491 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
492 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530493 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800494 dh.lockDevice.Lock()
495 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530496 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530497}
498
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700499// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530500// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800501func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000502 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700503 defer func() {
504 dh.lockDevice.Lock()
505 dh.isReadIndicationRoutineActive = false
506 dh.lockDevice.Unlock()
507 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700508 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700509 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700510 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700511 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400512
David Bainbridgef5879ca2019-12-13 21:17:54 +0000513 // Create an exponential backoff around re-enabling indications. The
514 // maximum elapsed time for the back off is set to 0 so that we will
515 // continue to retry. The max interval defaults to 1m, but is set
516 // here for code clarity
517 indicationBackoff := backoff.NewExponentialBackOff()
518 indicationBackoff.MaxElapsedTime = 0
519 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700520
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700521 dh.lockDevice.Lock()
522 dh.isReadIndicationRoutineActive = true
523 dh.lockDevice.Unlock()
524
Girish Gowdra3f974912020-03-23 20:35:18 -0700525Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700526 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400527 select {
528 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000529 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700530 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400531 default:
532 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100533
534 select {
535 case <-indications.Context().Done():
536 if err != nil {
537 logger.Warnw(ctx, "error-during-enable-indications",
538 log.Fields{"err": err,
539 "device-id": dh.device.Id})
540 }
541
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400542 // Use an exponential back off to prevent getting into a tight loop
543 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100544 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
545 "device-id": dh.device.Id,
546 "duration": duration,
547 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400548 if duration == backoff.Stop {
549 // If we reach a maximum then warn and reset the backoff
550 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100551 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530552 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530553 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400554 indicationBackoff.Reset()
555 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700556
557 // On failure process a backoff timer while watching for stopIndications
558 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700559 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700560 select {
561 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000562 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700563 if !backoffTimer.Stop() {
564 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700565 }
566 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700567 case <-backoffTimer.C:
568 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700569 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700570 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
571 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400572 }
573 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100574 default:
575 if err != nil {
576 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530577 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530578 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100579 // Close the stream, and re-initialize it
580 if err = indications.CloseSend(); err != nil {
581 // Ok to ignore here, because we landed here due to a problem on the stream
582 // In all probability, the closeSend call may fail
583 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
584 log.Fields{"err": err,
585 "device-id": dh.device.Id})
586 }
587 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
588 return err
589 }
590 // once we re-initialized the indication stream, continue to read indications
591 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700592 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100593 // Reset backoff if we have a successful receive
594 indicationBackoff.Reset()
595 // When OLT is admin down, ignore all indications.
596 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
597 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
598 log.Fields{"indication": indication,
599 "device-id": dh.device.Id})
600 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700601 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100602 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530603 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700604 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700606 // Close the send stream
607 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700608
Girish Gowdra3f974912020-03-23 20:35:18 -0700609 return nil
610}
611
612func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700613 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700614 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
615 if err != nil {
616 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
617 }
618 if indications == nil {
619 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
620 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700621 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700622 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400623}
624
625// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
626func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
627 switch indication.Data.(type) {
628 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
629 return true
630
631 default:
632 return false
633 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700634}
635
David K. Bainbridge794735f2020-02-11 21:01:37 -0800636func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700637 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000638 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530639 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700640 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530641 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700642 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000643 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000644 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530645 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000646 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800647 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000648 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800649 }
650 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651}
652
David K. Bainbridge794735f2020-02-11 21:01:37 -0800653// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530654func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700655 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 switch indication.Data.(type) {
657 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000658 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
659 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700660 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 -0800661 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400662 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800663 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700664 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000665 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
666 defer span.Finish()
667
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800669 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100670 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400671 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800672 }
673 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000674 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700675 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000676 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
677 defer span.Finish()
678
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700679 intfOperInd := indication.GetIntfOperInd()
680 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800681 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100682 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400683 _ = 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 -0800684 }
685 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700686 } else if intfOperInd.GetType() == "pon" {
687 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
688 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800689 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100690 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400691 _ = 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 -0800692 }
693 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000694 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700695 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000696 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530697 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530698 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700699 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000700 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
701 defer span.Finish()
702
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700703 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000704 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800705 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800706 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700707 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000708 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
709 defer span.Finish()
710
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700711 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000712 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800713 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800714 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700715 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000716 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
717 defer span.Finish()
718
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700719 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000720 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 -0800721 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000722 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400723 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800724 }
725 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700726 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000727 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
728 defer span.Finish()
729
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700730 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000731 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700732 "intf-type": pktInd.IntfId,
733 "intf-id": pktInd.IntfId,
734 "gem-port-id": pktInd.GemportId,
735 "port-no": pktInd.PortNo,
736 "device-id": dh.device.Id,
737 })
738
739 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000740 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700741 "intf-type": pktInd.IntfId,
742 "intf-id": pktInd.IntfId,
743 "gem-port-id": pktInd.GemportId,
744 "port-no": pktInd.PortNo,
745 "packet": hex.EncodeToString(pktInd.Pkt),
746 "device-id": dh.device.Id,
747 })
748 }
749
David K. Bainbridge794735f2020-02-11 21:01:37 -0800750 go func() {
751 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400752 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800753 }
754 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700755 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000756 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
757 defer span.Finish()
758
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700759 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700760 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700761 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000762 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
763 defer span.Finish()
764
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700765 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000766 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700767 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000768 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
769 defer span.Finish()
770
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700771 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000772 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
773 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700774 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530775}
776
777// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530778func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530779 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000780 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530781
Girish Gowdra618fa572021-09-01 17:19:29 -0700782 // instantiate the mcast handler routines.
783 for i := range dh.incomingMcastFlowOrGroup {
784 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
785 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
786 if !dh.mcastHandlerRoutineActive[i] {
787 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
788 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
789 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
790 // for incoming mcast flow/group to be processed serially.
791 dh.mcastHandlerRoutineActive[i] = true
792 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
793 }
794 }
795
Girish Gowdru0c588b22019-04-23 23:24:56 -0400796 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400797 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400798 DeviceId: dh.device.Id,
799 OperStatus: voltha.OperStatus_ACTIVE,
800 ConnStatus: voltha.ConnectStatus_REACHABLE,
801 }); err != nil {
802 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400803 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000804
805 //Clear olt communication failure event
806 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
807 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700808 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000809 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
810
Girish Gowdru0c588b22019-04-23 23:24:56 -0400811 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530812}
813
814// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530815func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000816 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400817
khenaidoo106c61a2021-08-11 18:05:46 -0400818 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400819 if err != nil || device == nil {
820 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000821 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400822 }
823
824 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400825
826 //Update the device oper state and connection status
827 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800828 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400829 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800830 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400831
khenaidoodc2116e2021-10-19 17:33:19 -0400832 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400833 DeviceId: cloned.Id,
834 OperStatus: cloned.OperStatus,
835 ConnStatus: cloned.ConnectStatus,
836 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000837 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400838 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400839
840 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400841 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400842 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000843 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400844 }
845 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400846 // Update onu state as down in onu adapter
847 onuInd := oop.OnuIndication{}
848 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400849
850 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
851 if err != nil {
852 return err
853 }
854 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400855 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400856 DeviceId: onuDevice.Id,
857 OnuIndication: &onuInd,
858 })
859 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800860 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400861 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400862 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800863 "onu-indicator": onuInd,
864 "device-type": onuDevice.Type,
865 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700866 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800867 } else {
868 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 -0700869 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400870 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800871 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700872 /* Discovered ONUs entries need to be cleared , since after OLT
873 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530874 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800875 dh.lockDevice.Unlock()
876
Neha Sharma96b7bf22020-06-15 10:37:32 +0000877 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700878 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530879}
880
881// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530882func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400883 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000884
885 // if the connection is already available, close the previous connection (olt reboot case)
886 if dh.clientCon != nil {
887 if err = dh.clientCon.Close(); err != nil {
888 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
889 } else {
890 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
891 }
892 }
893
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530894 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +0000895 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000896 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
897 grpc.WithInsecure(),
898 grpc.WithBlock(),
899 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000900 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000901 )),
902 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000903 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000904 )))
905
906 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530907 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530908 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000909 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400910 }
911 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530912}
913
914// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530915func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400916 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530917 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400918 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530919}
920
921// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530922func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530923 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000924 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400925
926 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400927 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530928 if err != nil || device == nil {
929 /*TODO: needs to handle error scenarios */
930 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
931 }
932 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000933 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400934
935 cloned := proto.Clone(device).(*voltha.Device)
936 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
937 cloned.OperStatus = voltha.OperStatus_UNKNOWN
938 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400939
khenaidoodc2116e2021-10-19 17:33:19 -0400940 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400941 DeviceId: cloned.Id,
942 OperStatus: cloned.OperStatus,
943 ConnStatus: cloned.ConnectStatus,
944 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530945 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 -0400946 }
947
Chaitrashree G S44124192019-08-07 20:21:36 -0400948 // 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 +0530949 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400950 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530951 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400952 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400953 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
954 // all the modules initialized and ready to handle incoming ONUs.
955
Thomas Lee S985938d2020-05-04 11:40:41 +0530956 err = dh.initializeDeviceHandlerModules(ctx)
957 if err != nil {
958 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 -0400959 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400960
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700961 go startHeartbeatCheck(ctx, dh)
962
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400963 return nil
964 }
965
khenaidoo106c61a2021-08-11 18:05:46 -0400966 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400967 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400968 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400969 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400970 }
khenaidoo106c61a2021-08-11 18:05:46 -0400971 dh.populateActivePorts(ctx, ports.Items)
972 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400973 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400974 }
975
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400976 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530977 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 -0400978 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530979
Neha Sharma96b7bf22020-06-15 10:37:32 +0000980 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000981
982 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000983 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000984 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700985
986 go startHeartbeatCheck(ctx, dh)
987
cuilin20187b2a8c32019-03-26 19:52:28 -0700988 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530989}
990
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400991func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700992 var err error
993 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400994
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000995 if dh.flowMgr != nil {
996 dh.StopAllFlowRoutines(ctx)
997 }
998
999 dh.CloseKVClient(ctx)
1000
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001001 if err != nil {
1002 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1003 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001004 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1005 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +00001006 // +1 is for NNI
1007 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1008 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001009 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001010 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1011 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1012 // There is only one NNI manager since multiple NNI is not supported for now
1013 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001014 // Instantiate resource manager
1015 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 -07001016 return olterrors.ErrResourceManagerInstantiating
1017 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001018 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001019 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1020 // the KV store to manage mcast group data. Provide the first instance (0th index)
1021 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1022 return olterrors.ErrGroupManagerInstantiating
1023 }
yasin saplid0566272021-12-21 09:10:30 +00001024 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001025 // Instantiate flow manager
1026 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001027 //Continue to check the rest of the ports
1028 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1029 } else {
1030 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001031 }
1032 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001033 /* TODO: Instantiate Alarm , stats , BW managers */
1034 /* Instantiating Event Manager to handle Alarms and KPIs */
1035 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1036
1037 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001038 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001039
1040 return nil
1041
1042}
1043
Neha Sharma96b7bf22020-06-15 10:37:32 +00001044func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001045 var err error
1046 var deviceInfo *oop.DeviceInfo
1047
Neha Sharma8f4e4322020-08-06 10:51:53 +00001048 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001049
1050 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001051 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001052 }
1053 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001054 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001055 }
1056
Neha Sharma96b7bf22020-06-15 10:37:32 +00001057 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001058 dh.device.Root = true
1059 dh.device.Vendor = deviceInfo.Vendor
1060 dh.device.Model = deviceInfo.Model
1061 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1062 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1063 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1064
1065 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001066 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001067 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001068 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001069 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001070 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001071 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001072 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001073 dh.device.MacAddress = genmac
1074 } else {
1075 dh.device.MacAddress = deviceInfo.DeviceId
1076 }
1077
1078 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001079 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001080 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001081 }
1082
1083 return deviceInfo, nil
1084}
1085
Neha Sharma96b7bf22020-06-15 10:37:32 +00001086func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001087 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001088
1089 defer func() {
1090 dh.lockDevice.Lock()
1091 dh.isCollectorActive = false
1092 dh.lockDevice.Unlock()
1093 }()
1094
1095 dh.lockDevice.Lock()
1096 dh.isCollectorActive = true
1097 dh.lockDevice.Unlock()
1098
Naga Manjunath7615e552019-10-11 22:35:47 +05301099 for {
1100 select {
1101 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001102 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301103 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001104 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001105
khenaidoo106c61a2021-08-11 18:05:46 -04001106 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001107 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001108 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001109 continue
1110 }
khenaidoo106c61a2021-08-11 18:05:46 -04001111 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301112 // NNI Stats
1113 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001114 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301115 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001116 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001117 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001118 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301119 }
1120 // PON Stats
1121 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001122 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301123 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1124 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001125 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001126 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301127 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001128 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001129
yasin sapli9e4c5092022-02-01 13:52:33 +00001130 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001131 if len(onuGemInfoLst) > 0 {
1132 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001133 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001134 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301135 }
1136 }
1137 }
1138}
1139
Mahir Gunyela2e68702022-12-07 00:00:42 -08001140// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301141func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001142 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001143 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301144 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301145
1146 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001147 cgClient, err := dh.coreClient.GetCoreServiceClient()
1148 if err != nil {
1149 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1150 return
1151 }
1152
1153 // Now, set the initial PM configuration for that device
1154 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001155 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301156 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301157}
1158
Mahir Gunyela2e68702022-12-07 00:00:42 -08001159// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001160func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1161 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001162 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301163 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001164 HwDesc: "open_pon",
1165 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001166 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001167 },
1168 SwitchFeatures: &of.OfpSwitchFeatures{
1169 NBuffers: 256,
1170 NTables: 2,
1171 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1172 of.OfpCapabilities_OFPC_TABLE_STATS |
1173 of.OfpCapabilities_OFPC_PORT_STATS |
1174 of.OfpCapabilities_OFPC_GROUP_STATS),
1175 },
1176 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301177}
1178
khenaidoo106c61a2021-08-11 18:05:46 -04001179// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001180func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001181 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001182 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001183 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001184 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001185 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1186 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()
1187 }
khenaidoo106c61a2021-08-11 18:05:46 -04001188 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Mahir Gunyela2e68702022-12-07 00:00:42 -08001189
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001190}
1191
Neha Sharma96b7bf22020-06-15 10:37:32 +00001192func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001193 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 -07001194 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001195 var deviceID string
1196 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001197 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001198
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001199 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001200 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001201 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 -07001202 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1203 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001204
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001205 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301206
1207 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1208
Neha Sharma96b7bf22020-06-15 10:37:32 +00001209 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 -07001210 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001211
khenaidoodc2116e2021-10-19 17:33:19 -04001212 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001213 ParentId: dh.device.Id,
1214 OnuId: omciInd.OnuId,
1215 ParentPortNo: ponPort,
1216 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001217 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301218 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001219 "intf-id": omciInd.IntfId,
1220 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001221 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001222 deviceType = onuDevice.Type
1223 deviceID = onuDevice.Id
1224 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001225 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001226 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001227 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001228 } else {
1229 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001230 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 +05301231 deviceType = onuInCache.(*OnuDevice).deviceType
1232 deviceID = onuInCache.(*OnuDevice).deviceID
1233 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001234 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001235 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001236
khenaidoodc2116e2021-10-19 17:33:19 -04001237 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001238 ParentDeviceId: proxyDeviceID,
1239 ChildDeviceId: deviceID,
1240 Message: omciInd.Pkt,
1241 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301242 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001243 "source": dh.openOLT.config.AdapterEndpoint,
1244 "device-type": deviceType,
1245 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001246 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001247 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001248 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001249 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301250}
1251
khenaidoo106c61a2021-08-11 18:05:46 -04001252// //ProcessInterAdapterMessage sends the proxied messages to the target device
1253// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1254// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001255// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001256// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001257// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001258// return dh.handleInterAdapterOmciMsg(ctx, msg)
1259// }
1260// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1261// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001262
kesavandb9f54fd2021-11-25 20:08:04 +05301263// ProxyOmciRequests sends the proxied OMCI message to the target device
1264func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301265 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1266 return status.Error(codes.Unavailable, "OLT unreachable")
1267 }
kesavandb9f54fd2021-11-25 20:08:04 +05301268 if omciMsgs.GetProxyAddress() == nil {
1269 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1270 if err != nil {
1271 return olterrors.NewErrNotFound("onu", log.Fields{
1272 "parent-device-id": dh.device.Id,
1273 "child-device-id": omciMsgs.ChildDeviceId}, err)
1274 }
1275 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1276 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1277 return olterrors.NewErrCommunication("send-failed", log.Fields{
1278 "parent-device-id": dh.device.Id,
1279 "child-device-id": omciMsgs.ChildDeviceId}, err)
1280 }
1281 } else {
1282 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1283 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1284 return olterrors.NewErrCommunication("send-failed", log.Fields{
1285 "parent-device-id": dh.device.Id,
1286 "child-device-id": omciMsgs.ChildDeviceId}, err)
1287 }
1288 }
1289 return nil
1290}
1291
1292func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1293 var intfID uint32
1294 var onuID uint32
1295 var connectStatus common.ConnectStatus_Types
1296 if onuDevice != nil {
1297 intfID = onuDevice.ProxyAddress.GetChannelId()
1298 onuID = onuDevice.ProxyAddress.GetOnuId()
1299 connectStatus = onuDevice.ConnectStatus
1300 } else {
1301 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1302 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1303 connectStatus = omciMsgs.GetConnectStatus()
1304 }
1305 if connectStatus != voltha.ConnectStatus_REACHABLE {
1306 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1307
1308 return olterrors.NewErrCommunication("unreachable", log.Fields{
1309 "intf-id": intfID,
1310 "onu-id": onuID}, nil)
1311 }
1312
1313 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1314 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1315
1316 onuSecOmciMsgList := omciMsgs.GetMessages()
1317
1318 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1319
1320 var omciMessage *oop.OmciMsg
1321 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1322 hex.Encode(hexPkt, onuSecOmciMsg)
1323 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1324
1325 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1326 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1327 //https://jira.opencord.org/browse/VOL-4604
1328 transid := extractOmciTransactionID(onuSecOmciMsg)
1329 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1330 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1331
1332 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1333 if err != nil {
1334 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1335 "intf-id": intfID,
1336 "onu-id": onuID,
1337 "message": omciMessage}, err)
1338 }
1339 }
1340 return nil
1341}
1342
khenaidoo106c61a2021-08-11 18:05:46 -04001343// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001344func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001345 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 -07001346
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301347 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1348 return status.Error(codes.Unavailable, "OLT unreachable")
1349 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001350 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001351 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001352 if err != nil {
1353 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001354 "parent-device-id": dh.device.Id,
1355 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001356 }
khenaidoo106c61a2021-08-11 18:05:46 -04001357 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1358 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001359 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001360 "parent-device-id": dh.device.Id,
1361 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001362 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001363 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001364 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1365 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001366 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001367 "parent-device-id": dh.device.Id,
1368 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001369 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001370 }
1371 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301372}
1373
khenaidoodc2116e2021-10-19 17:33:19 -04001374func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375 var intfID uint32
1376 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001377 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001378 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001379 intfID = onuDevice.ProxyAddress.GetChannelId()
1380 onuID = onuDevice.ProxyAddress.GetOnuId()
1381 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001382 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001383 intfID = omciMsg.GetProxyAddress().GetChannelId()
1384 onuID = omciMsg.GetProxyAddress().GetOnuId()
1385 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001386 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001387 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001388 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 -08001389
Thomas Lee S94109f12020-03-03 16:39:29 +05301390 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001391 "intf-id": intfID,
1392 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001393 }
1394
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001395 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1396 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301397 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001398 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001399 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1400 hex.Encode(hexPkt, omciMsg.Message)
1401 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1402
1403 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1404 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1405 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001406 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001407 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001408
Neha Sharma8f4e4322020-08-06 10:51:53 +00001409 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001410 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301411 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001412 "intf-id": intfID,
1413 "onu-id": onuID,
1414 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001415 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001416 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001417}
1418
David K. Bainbridge794735f2020-02-11 21:01:37 -08001419func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301420 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 +00001421 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001422 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001423 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001424 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301425 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301426 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001427 st, _ := status.FromError(err)
1428 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001429 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1430
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001431 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301432 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001433 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001434 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001435 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001436 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001437 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001438}
1439
Mahir Gunyela2e68702022-12-07 00:00:42 -08001440// getChildDevice function can be used in general to get child device, if not found in cache the function will
1441// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301442func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1443 var InCacheOnuDev *OnuDevice
1444 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1445 if onuInCache.(*OnuDevice).serialNumber == sn {
1446 InCacheOnuDev = onuInCache.(*OnuDevice)
1447 return false
1448 }
1449 return true
1450 })
1451 //Got the onu device from cache return
1452 if InCacheOnuDev != nil {
1453 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1454 return InCacheOnuDev
1455 }
1456 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1457 ParentId: dh.device.Id,
1458 SerialNumber: sn,
1459 ParentPortNo: parentPortNo,
1460 })
1461 //No device found in core return nil
1462 if onuDevice == nil {
1463 return nil
1464 }
1465 onuID := onuDevice.ProxyAddress.OnuId
1466 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1467 onuKey := dh.formOnuKey(intfID, onuID)
1468
1469 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1470 dh.onus.Store(onuKey, onuDev)
1471 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1472 return onuDev
1473}
1474
1475func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001476 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001477 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301478 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001479
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301480 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1481 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1482 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1483 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1484 if onuDev != nil {
1485 var onuGemInfo *rsrcMgr.OnuGemInfo
1486 var err error
1487 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1488 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1489 return false, err
1490 }
1491 if onuGemInfo != nil {
1492 for _, uni := range onuGemInfo.UniPorts {
1493 uniID := plt.UniIDFromPortNum(uni)
1494 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1495 if len(tpIDs) != 0 {
1496 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1497 tpInstExists = true
1498 break
1499 }
1500 }
1501 }
1502 }
1503 return tpInstExists, nil
1504 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301505
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301506 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1507 ParentId: dh.device.Id,
1508 SerialNumber: sn,
1509 ParentPortNo: parentPortNo,
1510 })
1511 if onuDevice != nil {
1512 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1513 return true, nil
1514 }
1515 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1516
1517 return false, nil
1518
1519}
1520
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001521// processDiscONULOSClear clears the LOS Alarm if it's needed
1522func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301523 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001524 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301525
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001526 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1527 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1528 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1529 OnuLosRaise event sent for it */
1530 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1531 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1532 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1533 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1534 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1535 "currentIntfId": onuDiscInd.GetIntfId()})
1536 // TODO:: Should we need to ignore raising OnuLosClear event
1537 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301538 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001539 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1540 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1541 alarmInd.LosStatus = statusCheckOff
1542 go func() {
1543 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1544 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1545 }
1546 }()
1547 // stop iterating
1548 return false
1549 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301550 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001551 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301552}
1553
1554func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
1555 channelID := onuDiscInd.GetIntfId()
1556 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1557
1558 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
1559 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1560
1561 tpInstExists, errtp := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1562 if errtp != nil {
1563 return errtp
1564 }
1565 if tpInstExists {
1566 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001567 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001568 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001569 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001570 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1571
1572 // if the ONU existed, handle the LOS Alarm
1573 if existing {
1574
1575 if inProcess.(bool) {
1576 // if we're currently processing the ONU on a different thread, do nothing
1577 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1578 return nil
1579 }
1580 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1581 // then continue processing it
1582 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1583
1584 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001585 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301586 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001587
1588 defer func() {
1589 // once the function completes set the value to false so that
1590 // we know the processing has inProcess.
1591 // Note that this is done after checking if we are already processing
1592 // to avoid changing the value from a different thread
1593 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1594 dh.discOnus.Store(sn, false)
1595 }()
1596
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001597 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001598
1599 // check the ONU is already know to the OLT
1600 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001601 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001602 ParentId: dh.device.Id,
1603 SerialNumber: sn,
1604 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001605
1606 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001607 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 -08001608 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001609 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 -08001610 switch e.Code() {
1611 case codes.Internal:
1612 // this probably means NOT FOUND, so just create a new device
1613 onuDevice = nil
1614 case codes.DeadlineExceeded:
1615 // if the call times out, cleanup and exit
1616 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001617 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001618 }
1619 }
1620 }
1621
1622 if onuDevice == nil {
1623 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001625 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001626 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001627 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001628
Neha Sharma96b7bf22020-06-15 10:37:32 +00001629 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001630
1631 if err != nil {
1632 // if we can't create an ID in resource manager,
1633 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001634 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001635 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001636 "pon-intf-id": ponintfid,
1637 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001638 }
1639
khenaidoodc2116e2021-10-19 17:33:19 -04001640 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001641 ParentId: dh.device.Id,
1642 ParentPortNo: parentPortNo,
1643 ChannelId: channelID,
1644 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1645 SerialNumber: sn,
1646 OnuId: onuID,
1647 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001648 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001649 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 +05301650 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001651 "pon-intf-id": ponintfid,
1652 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001653 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001654 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 -07001655 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001656 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001657 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301658 log.Fields{"onuDevice": onuDevice,
1659 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001660 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301661 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001662 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001663
khenaidoo106c61a2021-08-11 18:05:46 -04001664 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1665 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1666 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1667 cancel()
1668 if err != nil {
1669 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1670 }
1671
Matteo Scandolo945e4012019-12-12 14:16:11 -08001672 // we can now use the existing ONU Id
1673 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001674 //Insert the ONU into cache to use in OnuIndication.
1675 //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 +00001676 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001677 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301678 "intfId": onuDiscInd.GetIntfId(),
1679 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001680 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001681
khenaidoo106c61a2021-08-11 18:05:46 -04001682 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301683 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001684 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301685 log.Fields{"onu": onuDev,
1686 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001687
khenaidoodc2116e2021-10-19 17:33:19 -04001688 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001689 DeviceId: onuDevice.Id,
1690 ParentDeviceId: dh.device.Id,
1691 OperStatus: common.OperStatus_DISCOVERED,
1692 ConnStatus: common.ConnectStatus_REACHABLE,
1693 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301694 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001695 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001696 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001697 }
khenaidoo106c61a2021-08-11 18:05:46 -04001698
Neha Sharma96b7bf22020-06-15 10:37:32 +00001699 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001700 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301701 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001703 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 }
1705 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001706}
1707
Mahir Gunyelb0046752021-02-26 13:51:05 -08001708func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001709
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001710 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001711 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001712 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001713 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301715 log.Fields{"onuId": onuInd.OnuId,
1716 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301717 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001718 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001719 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301720
David K. Bainbridge794735f2020-02-11 21:01:37 -08001721 errFields := log.Fields{"device-id": dh.device.Id}
1722
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301723 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1724
Mahir Gunyele77977b2019-06-27 05:36:22 -07001725 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1726 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001727 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001728 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001729 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001730 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1731 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001732 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001733 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001734 errFields["onu-id"] = onuInd.OnuId
1735 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001736 }
khenaidoodc2116e2021-10-19 17:33:19 -04001737 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001738 ParentId: dh.device.Id,
1739 SerialNumber: serialNumber,
1740 OnuId: onuInd.OnuId,
1741 ParentPortNo: ponPort,
1742 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001743 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001744
David K. Bainbridge794735f2020-02-11 21:01:37 -08001745 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001746 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001747 }
1748
David K. Bainbridge794735f2020-02-11 21:01:37 -08001749 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001750 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001751 "previousIntfId": onuDevice.ParentPortNo,
1752 "currentIntfId": ponPort})
1753 }
1754
1755 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001756 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301757 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1758 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301759 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001760 }
1761 if !foundInCache {
1762 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1763
khenaidoo106c61a2021-08-11 18:05:46 -04001764 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 -08001765
1766 }
kesavand7cf3a052020-08-28 12:49:18 +05301767 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001768 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001769 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301770 }
1771 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001772 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001773 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001774 }
1775 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001776}
1777
Neha Sharma96b7bf22020-06-15 10:37:32 +00001778func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 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 -07001780 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1781 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1782 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1783 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001784 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001785 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1786 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001787 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001788 onuInd.OperState = "down"
1789 }
1790 }
1791
David K. Bainbridge794735f2020-02-11 21:01:37 -08001792 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001793 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001794 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 -04001795
khenaidoodc2116e2021-10-19 17:33:19 -04001796 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001797 DeviceId: onuDevice.Id,
1798 OnuIndication: onuInd,
1799 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001800 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301801 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001802 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001803 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001804 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001805 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001806 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001807 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001808 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001809 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001810 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001811}
1812
cuilin20187b2a8c32019-03-26 19:52:28 -07001813func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1814 if serialNum != nil {
1815 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001816 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001817 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001818}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001819func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1820 decodedStr, err := hex.DecodeString(serialNum[4:])
1821 if err != nil {
1822 return nil, err
1823 }
1824 return &oop.SerialNumber{
1825 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001826 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001827 }, nil
1828}
cuilin20187b2a8c32019-03-26 19:52:28 -07001829
1830func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001831 if len(vendorSpecific) > 3 {
1832 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1833 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1834 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1835 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1836 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1837 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1838 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1839 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1840 return tmp
1841 }
1842 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001843}
1844
Mahir Gunyela2e68702022-12-07 00:00:42 -08001845// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001846func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301847 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001848}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001849
Mahir Gunyela2e68702022-12-07 00:00:42 -08001850// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001851func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1852 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301853 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001854 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301855 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001856
khenaidoodc2116e2021-10-19 17:33:19 -04001857 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001858 ParentId: dh.device.Id,
1859 OnuId: onuID,
1860 ParentPortNo: parentPort,
1861 })
1862
Girish Gowdru0c588b22019-04-23 23:24:56 -04001863 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001864 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001865 "intf-id": parentPort,
1866 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001867 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001868 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 -08001869 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301870}
1871
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001872// SendPacketInToCore sends packet-in to core
1873// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1874// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001876 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001877 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001878 "port": logicalPort,
1879 "packet": hex.EncodeToString(packetPayload),
1880 "device-id": dh.device.Id,
1881 })
1882 }
khenaidoo106c61a2021-08-11 18:05:46 -04001883
khenaidoodc2116e2021-10-19 17:33:19 -04001884 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001885 DeviceId: dh.device.Id,
1886 Port: logicalPort,
1887 Packet: packetPayload,
1888 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301889 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001890 "source": "adapter",
1891 "destination": "core",
1892 "device-id": dh.device.Id,
1893 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001894 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001895 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001896 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001897 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001898 "packet": hex.EncodeToString(packetPayload),
1899 "device-id": dh.device.Id,
1900 })
1901 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001902 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001903}
1904
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001905// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001906func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001907 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001908
1909 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1910 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001911 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001912 }
1913
Kent Hagermane6ff1012020-07-14 15:07:53 -04001914 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001915 metrics := dh.metrics.GetSubscriberMetrics()
1916 for _, m := range pmConfigs.Metrics {
1917 metrics[m.Name].Enabled = m.Enabled
1918
1919 }
1920 }
1921}
1922
khenaidoodc2116e2021-10-19 17:33:19 -04001923func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001924 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001925 var errorsList []error
1926
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001927 if dh.getDeviceDeletionInProgressFlag() {
1928 // The device itself is going to be reset as part of deletion. So nothing to be done.
1929 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1930 return nil
1931 }
1932
Girish Gowdru0c588b22019-04-23 23:24:56 -04001933 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001934 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001935 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001936
Neha Sharma96b7bf22020-06-15 10:37:32 +00001937 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301938 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001939 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301940 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001941 if flow_utils.HasGroup(flow) {
1942 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1943 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001944 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
1945 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1946 } else {
1947 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
1948 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001949 }
Girish Gowdracefae192020-03-19 18:14:10 -07001950 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01001951 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
1952 //The flow we want to remove is not there, there is no need to throw an error
1953 logger.Warnw(ctx, "flow-to-remove-not-found",
1954 log.Fields{
1955 "ponIf": intfID,
1956 "flowToRemove": flow,
1957 "error": err,
1958 })
1959 } else {
1960 errorsList = append(errorsList, err)
1961 }
Girish Gowdracefae192020-03-19 18:14:10 -07001962 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001963 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301964
1965 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00001966 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001967 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301968 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001969 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301970 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001971 if flow_utils.HasGroup(flow) {
1972 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1973 } else {
yasin saplid0566272021-12-21 09:10:30 +00001974 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001975 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1976 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1977 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1978 } else {
yasin saplid0566272021-12-21 09:10:30 +00001979 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001980 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001981 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001982 if err != nil {
1983 errorsList = append(errorsList, err)
1984 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301985 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001986 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001987
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001988 return errorsList
1989}
1990
1991func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1992 var err error
1993 var errorsList []error
1994
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001995 if dh.getDeviceDeletionInProgressFlag() {
1996 // The device itself is going to be reset as part of deletion. So nothing to be done.
1997 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1998 return nil
1999 }
2000
Girish Gowdracefae192020-03-19 18:14:10 -07002001 // 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 +00002002 if groups != nil {
2003 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002004 // err = dh.groupMgr.AddGroup(ctx, group)
2005 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002006 if err != nil {
2007 errorsList = append(errorsList, err)
2008 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002009 }
2010 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002011 // err = dh.groupMgr.ModifyGroup(ctx, group)
2012 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002013 if err != nil {
2014 errorsList = append(errorsList, err)
2015 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002016 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002017 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002018 // err = dh.groupMgr.DeleteGroup(ctx, group)
2019 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002020 if err != nil {
2021 errorsList = append(errorsList, err)
2022 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002023 }
2024 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002025
2026 return errorsList
2027}
2028
Mahir Gunyela2e68702022-12-07 00:00:42 -08002029// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002030func (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 -07002031
2032 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002033
2034 if dh.getDeviceDeletionInProgressFlag() {
2035 // The device itself is going to be reset as part of deletion. So nothing to be done.
2036 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2037 return nil
2038 }
2039
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002040 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2041 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2042 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002043 if len(errorsList) > 0 {
2044 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2045 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002046 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002047 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302048}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002049
Mahir Gunyela2e68702022-12-07 00:00:42 -08002050// DisableDevice disables the given device
2051// It marks the following for the given device:
2052// Device-Handler Admin-State : down
2053// Device Port-State: UNKNOWN
2054// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002055func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002056 /* On device disable ,admin state update has to be done prior sending request to agent since
2057 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002058 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002059 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002060 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002061 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002062 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002063 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002064 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002065 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002066 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002067 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302068
2069 dh.discOnus = sync.Map{}
2070 dh.onus = sync.Map{}
2071
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002072 dh.lockDevice.RLock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302073 //stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002074 if dh.isCollectorActive {
2075 dh.stopCollector <- true
2076 }
2077 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302078
Neha Sharma96b7bf22020-06-15 10:37:32 +00002079 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002080 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05302081 //Update device Admin state
2082 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002083
kdarapu1afeceb2020-02-12 01:38:09 -05002084 // 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 -04002085 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002086 DeviceId: cloned.Id,
2087 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2088 OperStatus: voltha.OperStatus_UNKNOWN,
2089 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002090 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002091 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002092 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002093 return nil
2094}
2095
Neha Sharma96b7bf22020-06-15 10:37:32 +00002096func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002097 // Update onu state as unreachable in onu adapter
2098 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302099 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002100
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002101 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002102 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002103 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002104 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 -04002105 }
2106 if onuDevices != nil {
2107 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002108 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002109 DeviceId: onuDevice.Id,
2110 OnuIndication: &onuInd,
2111 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002112 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002113 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002114 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002115 }
2116
2117 }
2118 }
2119
2120}
2121
Mahir Gunyela2e68702022-12-07 00:00:42 -08002122// ReenableDevice re-enables the olt device after disable
2123// It marks the following for the given device:
2124// Device-Handler Admin-State : up
2125// Device Port-State: ACTIVE
2126// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002127func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002128 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302129 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002130 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302131 }
2132 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002133 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002134
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002135 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002136 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002137 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002138 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002139 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2140 } else {
2141 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2142 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2143 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002144 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002145 if retError == nil {
2146 //Update the device oper status as ACTIVE
2147 device.OperStatus = voltha.OperStatus_ACTIVE
2148 } else {
2149 //Update the device oper status as FAILED
2150 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002151 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002152 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002153
khenaidoodc2116e2021-10-19 17:33:19 -04002154 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002155 DeviceId: device.Id,
2156 OperStatus: device.OperStatus,
2157 ConnStatus: device.ConnectStatus,
2158 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302159 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002160 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002161 "connect-status": device.ConnectStatus,
2162 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002163 }
kesavand39e0aa32020-01-28 20:58:50 -05002164
Neha Sharma96b7bf22020-06-15 10:37:32 +00002165 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002166
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002167 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002168}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002169
npujarec5762e2020-01-01 14:08:48 +05302170func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002171 var uniID uint32
2172 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302173 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002174 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002175 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002176 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002177 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2178 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2179 } else {
2180 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2181 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
2182 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002183 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002185 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002186 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002187 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002188 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00002189 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002190 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002191 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002192 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00002193 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002194 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302195 }
yasin saplibddc2d72022-02-08 13:10:17 +00002196 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2197 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002198 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302199 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002200 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002201 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002202 logger.Debugw(ctx, "failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002203 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002204 }
2205 return nil
2206}
2207
Devmalya Paul495b94a2019-08-27 19:42:00 -04002208// 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 +05302209func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002210 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002211 /* Clear the KV store data associated with the all the UNI ports
2212 This clears up flow data and also resource map data for various
2213 other pon resources like alloc_id and gemport_id
2214 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002215
2216 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002217
2218 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002219
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002220 dh.cleanupDeviceResources(ctx)
2221 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002222
Himani Chawla49a5d562020-11-25 11:53:44 +05302223 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002224 // Stop the Stats collector
2225 if dh.isCollectorActive {
2226 dh.stopCollector <- true
2227 }
2228 // stop the heartbeat check routine
2229 if dh.isHeartbeatCheckActive {
2230 dh.stopHeartbeatCheck <- true
2231 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302232 // Stop the read indication only if it the routine is active
2233 if dh.isReadIndicationRoutineActive {
2234 dh.stopIndications <- true
2235 }
2236 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002237 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002238 //Reset the state
2239 if dh.Client != nil {
2240 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302241 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002242 }
2243 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002244 // There is no need to update the core about operation status and connection status of the OLT.
2245 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2246 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2247 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002248
khenaidoo7eb2d672021-10-22 19:08:50 -04002249 // Stop the adapter grpc clients for that parent device
2250 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002251 return nil
2252}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002253
2254// StopAllFlowRoutines stops all flow routines
2255func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2256 var wg sync.WaitGroup
2257 wg.Add(1) // for the mcast routine below to finish
2258 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2259 for _, flMgr := range dh.flowMgr {
2260 if flMgr != nil {
2261 wg.Add(1) // for the flow handler routine below to finish
2262 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2263 }
2264 }
2265 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2266 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2267 } else {
2268 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2269 }
2270}
2271
Kent Hagermane6ff1012020-07-14 15:07:53 -04002272func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002273
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002274 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302275 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002276 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002277 var err error
yasin sapli9e4c5092022-02-01 13:52:33 +00002278 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002279 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002280 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002281 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002282 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302283 }
2284 }
yasin saplibddc2d72022-02-08 13:10:17 +00002285 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx)
2286 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002287 dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002288 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2289 logger.Debug(ctx, err)
2290 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002291 }
yasin saplibddc2d72022-02-08 13:10:17 +00002292 // Clean up NNI manager's data
2293 _ = dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002294 }
A R Karthick1f85b802019-10-11 05:06:05 +00002295
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002296 dh.CloseKVClient(ctx)
2297
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002298 // Take one final sweep at cleaning up KV store for the OLT device
2299 // Clean everything at <base-path-prefix>/openolt/<device-id>
2300 kvClient, err := kvstore.NewEtcdClient(ctx, dh.openOLT.KVStoreAddress, rsrcMgr.KvstoreTimeout, log.FatalLevel)
2301 if err == nil {
2302 kvBackend := &db.Backend{
2303 Client: kvClient,
2304 StoreType: dh.openOLT.KVStoreType,
2305 Address: dh.openOLT.KVStoreAddress,
2306 Timeout: rsrcMgr.KvstoreTimeout,
2307 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, dh.cm.Backend.PathPrefix, dh.device.Id)}
2308 _ = kvBackend.DeleteWithPrefix(ctx, "")
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002309 kvBackend.Client.Close(ctx)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002310 }
2311
Devmalya Paul495b94a2019-08-27 19:42:00 -04002312 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302313 dh.onus.Range(func(key interface{}, value interface{}) bool {
2314 dh.onus.Delete(key)
2315 return true
2316 })
2317
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002318 /*Delete discovered ONU map for the device*/
2319 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2320 dh.discOnus.Delete(key)
2321 return true
2322 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002323}
2324
Mahir Gunyela2e68702022-12-07 00:00:42 -08002325// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002326func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002327 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302328 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002329 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002330 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002331 return nil
2332}
2333
David K. Bainbridge794735f2020-02-11 21:01:37 -08002334func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002335 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002336 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002337 "packet-indication": *packetIn,
2338 "device-id": dh.device.Id,
2339 "packet": hex.EncodeToString(packetIn.Pkt),
2340 })
2341 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002342 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2343 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2344 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002345 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002346 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002347 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002348 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002349 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002350 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002351 "logical-port-num": logicalPortNum,
2352 "device-id": dh.device.Id,
2353 "packet": hex.EncodeToString(packetIn.Pkt),
2354 })
2355 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002356
khenaidoodc2116e2021-10-19 17:33:19 -04002357 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002358 DeviceId: dh.device.Id,
2359 Port: logicalPortNum,
2360 Packet: packetIn.Pkt,
2361 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302362 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002363 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302364 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002365 "device-id": dh.device.Id,
2366 "packet": hex.EncodeToString(packetIn.Pkt),
2367 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002368 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002369
Matteo Scandolo92186242020-06-12 10:54:18 -07002370 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002371 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002372 "packet": hex.EncodeToString(packetIn.Pkt),
2373 "device-id": dh.device.Id,
2374 })
2375 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002376 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002377}
2378
Mahir Gunyela2e68702022-12-07 00:00:42 -08002379// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2380func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2381 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2382 if err != nil {
2383 return olterrors.NewErrInvalidValue(log.Fields{
2384 "egress-nni-port": egressPortNo,
2385 "device-id": dh.device.Id,
2386 }, err)
2387 }
2388 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2389
2390 if logger.V(log.DebugLevel) {
2391 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2392 "uplink-pkt": uplinkPkt,
2393 "packet": hex.EncodeToString(packet.Data),
2394 "device-id": dh.device.Id,
2395 })
2396 }
2397
2398 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2399 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2400 "packet": hex.EncodeToString(packet.Data),
2401 "device-id": dh.device.Id,
2402 }, err)
2403 }
2404 return nil
2405}
2406
2407// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2408func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2409 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2410 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2411 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2412 // Do not packet-out lldp packets on uni port.
2413 // ONOS has no clue about uni/nni ports, it just packets out on all
2414 // available ports on the Logical Switch. It should not be interested
2415 // in the UNI links.
2416 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2417 "device-id": dh.device.Id,
2418 })
2419 return nil
2420 }
2421 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2422 if innerEthType == 0x8100 {
2423 // q-in-q 802.1ad or 802.1q double tagged packet.
2424 // slice out the outer tag.
2425 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2426 if logger.V(log.DebugLevel) {
2427 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2428 "packet-data": hex.EncodeToString(packet.Data),
2429 "device-id": dh.device.Id,
2430 })
2431 }
2432 }
2433 }
2434 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2435 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2436 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2437 var gemPortID uint32
2438 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2439 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2440 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2441 }
2442 if err != nil {
2443 // In this case the openolt agent will receive the gemPortID as 0.
2444 // The agent tries to retrieve the gemPortID in this case.
2445 // This may not always succeed at the agent and packetOut may fail.
2446 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2447 "intf-id": intfID,
2448 "onu-id": onuID,
2449 "uni-id": uniID,
2450 "packet": hex.EncodeToString(packet.Data),
2451 "device-id": dh.device.Id,
2452 "error": err,
2453 })
2454 }
2455
2456 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2457 if logger.V(log.DebugLevel) {
2458 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2459 "egress-port-no": egressPortNo,
2460 "intf-id": intfID,
2461 "onu-id": onuID,
2462 "uni-id": uniID,
2463 "gem-port-id": gemPortID,
2464 "packet": hex.EncodeToString(packet.Data),
2465 "device-id": dh.device.Id,
2466 })
2467 }
2468
2469 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2470 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2471 "source": "adapter",
2472 "destination": "onu",
2473 "egress-port-number": egressPortNo,
2474 "intf-id": intfID,
2475 "oni-id": onuID,
2476 "uni-id": uniID,
2477 "gem-port-id": gemPortID,
2478 "packet": hex.EncodeToString(packet.Data),
2479 "device-id": dh.device.Id,
2480 }, err)
2481 }
2482 return nil
2483}
2484
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002485// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002486func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002487 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002488 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002489 "device-id": dh.device.Id,
2490 "egress-port-no": egressPortNo,
2491 "pkt-length": len(packet.Data),
2492 "packet": hex.EncodeToString(packet.Data),
2493 })
2494 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002495
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002496 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002497 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002498 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002499 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002500 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002501 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002502 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002503 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302504 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002505 "egressPortType": egressPortType,
2506 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302507 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002508 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002509 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002510 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002511}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002512
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002513func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2514 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002515}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302516
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002517func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002518
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002519 defer func() {
2520 dh.lockDevice.Lock()
2521 dh.isHeartbeatCheckActive = false
2522 dh.lockDevice.Unlock()
2523 }()
2524
2525 dh.lockDevice.Lock()
2526 dh.isHeartbeatCheckActive = true
2527 dh.lockDevice.Unlock()
2528
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302529 // start the heartbeat check towards the OLT.
2530 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302531 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302532
2533 for {
2534 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2535 select {
2536 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002537 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002538 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002539 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302540 if timerCheck == nil {
2541 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002542 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302543 }
2544 } else {
2545 if timerCheck != nil {
2546 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002547 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302548 }
2549 timerCheck = nil
2550 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302551 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2552 if dh.heartbeatSignature == 0 {
2553 // First time the signature will be 0, update the signture to DB when not found.
2554 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2555 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2556 }
2557 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2558
2559 dh.lockDevice.RLock()
2560 // Stop the read indication only if it the routine is active
2561 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2562 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2563 // on next execution of the readIndication routine.
2564 if !dh.isReadIndicationRoutineActive {
2565 // Start reading indications
2566 go func() {
2567 if err = dh.readIndications(ctx); err != nil {
2568 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2569 }
2570 }()
2571 }
2572 dh.lockDevice.RUnlock()
2573
2574 } else {
2575 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2576 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2577 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2578 go dh.updateStateRebooted(ctx)
2579 }
2580
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302581 }
2582 cancel()
2583 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002584 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302585 return
2586 }
2587 }
2588}
2589
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002590func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002591 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002592 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002593 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2594 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2595 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2596 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2597 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002598 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002599 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2600 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002601 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302602
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302603 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002604 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002605 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002606 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002607 DeviceId: dh.device.Id,
2608 OperStatus: voltha.OperStatus_UNKNOWN,
2609 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2610 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002611 _ = 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 -04002612 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302613 /*
2614 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2615 DeviceId: dh.device.Id,
2616 PortTypeFilter: 0,
2617 OperStatus: voltha.OperStatus_UNKNOWN,
2618 }); err != nil {
2619 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2620 }
2621 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002622
2623 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002624 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002625 cloned := proto.Clone(device).(*voltha.Device)
2626 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2627 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2628 dh.device = cloned // update local copy of the device
2629 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002630
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002631 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002632 // Stop the Stats collector
2633 if dh.isCollectorActive {
2634 dh.stopCollector <- true
2635 }
2636 // stop the heartbeat check routine
2637 if dh.isHeartbeatCheckActive {
2638 dh.stopHeartbeatCheck <- true
2639 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002640 // Stop the read indication only if it the routine is active
2641 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2642 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2643 // on next execution of the readIndication routine.
2644 if dh.isReadIndicationRoutineActive {
2645 dh.stopIndications <- true
2646 }
2647 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002648 dh.transitionMap.Handle(ctx, DeviceInit)
2649
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302650 }
2651}
kesavand39e0aa32020-01-28 20:58:50 -05002652
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302653func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2654 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2655 if err != nil || device == nil {
2656 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2657 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2658 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2659 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2660 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2661 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2662 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2663 return
2664 }
2665
2666 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2667 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2668 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2669 DeviceId: dh.device.Id,
2670 OperStatus: voltha.OperStatus_REBOOTED,
2671 ConnStatus: voltha.ConnectStatus_REACHABLE,
2672 }); err != nil {
2673 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2674 }
2675
2676 dh.lockDevice.RLock()
2677 // Stop the read indication only if it the routine is active
2678 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2679 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2680 // on next execution of the readIndication routine.
2681 if dh.isReadIndicationRoutineActive {
2682 dh.stopIndications <- true
2683 }
2684 dh.lockDevice.RUnlock()
2685
2686 //raise olt communication failure event
2687 raisedTs := time.Now().Unix()
2688 cloned := proto.Clone(device).(*voltha.Device)
2689 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2690 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2691 dh.device = cloned // update local copy of the device
2692 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2693
2694 dh.cleanupDeviceResources(ctx)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002695 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002696
2697 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302698 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002699 if dh.isCollectorActive {
2700 dh.stopCollector <- true
2701 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302702 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002703 if dh.isHeartbeatCheckActive {
2704 dh.stopHeartbeatCheck <- true
2705 }
2706 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302707
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002708 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302709
2710 //reset adapter reconcile flag
2711 dh.adapterPreviouslyConnected = false
2712 for {
2713
2714 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2715 if err != nil || childDevices == nil {
2716 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2717 continue
2718 }
2719 if len(childDevices.Items) == 0 {
2720 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
2721 break
2722 } else {
2723 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
2724 time.Sleep(5 * time.Second)
2725 }
2726
2727 }
2728 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
2729 dh.transitionMap.Handle(ctx, DeviceInit)
2730
2731}
2732
kesavand39e0aa32020-01-28 20:58:50 -05002733// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002734func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2735 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2736 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002737}
2738
2739// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002740func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2741 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2742 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002743}
2744
Mahir Gunyela2e68702022-12-07 00:00:42 -08002745// 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 +00002746func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2747 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002748 if port.GetType() == voltha.Port_ETHERNET_NNI {
2749 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002750 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302751 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302752 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002753 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002754 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002755 }
2756 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002757 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002758 ponIntf := &oop.Interface{IntfId: ponID}
2759 var operStatus voltha.OperStatus_Types
2760 if enablePort {
2761 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302762 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002763
2764 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302765 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002766 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002767 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002768 }
2769 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002770 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002771 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002772 } else {
2773 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302774 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002775 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302776 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002777 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002778 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002779 }
2780 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002781 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002782 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002783 }
khenaidoodc2116e2021-10-19 17:33:19 -04002784 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002785 DeviceId: dh.device.Id,
2786 PortType: voltha.Port_PON_OLT,
2787 PortNo: port.PortNo,
2788 OperStatus: operStatus,
2789 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302790 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302791 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002792 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002793 }
2794 return nil
2795}
2796
Mahir Gunyela2e68702022-12-07 00:00:42 -08002797// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002798func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002799 // Disable the port and update the oper_port_status to core
2800 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002801 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002802 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002803 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302804 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302805 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002806 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002807 }
2808 }
2809 }
2810 return nil
2811}
2812
Mahir Gunyela2e68702022-12-07 00:00:42 -08002813// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002814func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2815 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2816 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002817 if port.Type == voltha.Port_ETHERNET_NNI {
2818 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002819 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002820 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002821 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002822 }
2823 }
2824 if port.Type == voltha.Port_PON_OLT {
2825 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002826 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002827 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002828 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002829 }
2830 }
2831 }
2832}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002833
2834// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002835func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002836 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07002837 if dh.getDeviceDeletionInProgressFlag() {
2838 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
2839 // will reboot, so everything will be reset on the pOLT too.
2840 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
2841 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
2842 return nil
2843 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002844 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002845 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002846
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002847 var sn *oop.SerialNumber
2848 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002849 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302850 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002851 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302852 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002853 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002854 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002855
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002856 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002857 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00002858 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002859 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2860 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2861 "device-id": dh.device.Id,
2862 "intf-id": intfID,
2863 "onuID": onuID,
2864 "err": err})
2865 } else {
2866 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00002867 // Delete flows from device before schedulers and queue
2868 // Clear flowids for gem cache.
2869 removedFlows := []uint64{}
2870 for _, gem := range onuGem.GemPorts {
2871 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
2872 for _, flowID := range flowIDs {
2873 //multiple gem port can have the same flow id
2874 //it is better to send only one flowRemove request to the agent
2875 var alreadyRemoved bool
2876 for _, removedFlowID := range removedFlows {
2877 if removedFlowID == flowID {
2878 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
2879 alreadyRemoved = true
2880 break
2881 }
2882 }
2883 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002884 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00002885 removedFlows = appendUnique64bit(removedFlows, flowID)
2886 }
2887 }
2888 }
2889 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
2890 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002891 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2892 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2893 "device-id": dh.device.Id,
2894 "onu-device": onu,
2895 "err": err})
2896 }
yasin saplibddc2d72022-02-08 13:10:17 +00002897 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002898 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2899 "intf-id": intfID,
2900 "onu-device": onu,
2901 "onu-gem": onuGem,
2902 "err": err})
2903 //Not returning error on cleanup.
2904 }
2905 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302906
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002907 }
yasin saplibddc2d72022-02-08 13:10:17 +00002908 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002909 dh.onus.Delete(onuKey)
2910 dh.discOnus.Delete(onuSn)
2911
2912 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002913 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302914 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302915 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002916 "onu-id": onuID}, err).Log()
2917 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002918
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002919 return nil
2920}
Mahir Gunyela2e68702022-12-07 00:00:42 -08002921func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
2922 flow := &oop.Flow{FlowId: flowID}
2923 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2924 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
2925 "device-id": dh.device.Id})
2926 } else {
2927 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
2928 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
2929 "device-id": dh.device.Id,
2930 "err": err})
2931 }
2932 }
2933}
Girish Gowdracefae192020-03-19 18:14:10 -07002934
2935func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002936 for _, field := range flow_utils.GetOfbFields(flow) {
2937 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002938 return field.GetPort()
2939 }
2940 }
2941 return InvalidPort
2942}
2943
2944func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002945 for _, action := range flow_utils.GetActions(flow) {
2946 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002947 if out := action.GetOutput(); out != nil {
2948 return out.GetPort()
2949 }
2950 }
2951 }
2952 return InvalidPort
2953}
2954
Girish Gowdracefae192020-03-19 18:14:10 -07002955func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2956 inPort := getInPortFromFlow(flow)
2957 outPort := getOutPortFromFlow(flow)
2958
2959 if inPort == InvalidPort || outPort == InvalidPort {
2960 return inPort, outPort
2961 }
2962
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002963 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002964 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002965 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002966 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002967 return uniPort, outPort
2968 }
2969 }
2970 } else {
2971 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002972 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002973 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002974 return inPort, uniPort
2975 }
2976 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002977 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002978 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002979 return uniPort, outPort
2980 }
2981 }
2982 }
2983
2984 return InvalidPort, InvalidPort
2985}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002986
2987func extractOmciTransactionID(omciPkt []byte) uint16 {
2988 if len(omciPkt) > 3 {
2989 d := omciPkt[0:2]
2990 transid := binary.BigEndian.Uint16(d)
2991 return transid
2992 }
2993 return 0
2994}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002995
2996// StoreOnuDevice stores the onu parameters to the local cache.
2997func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2998 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2999 dh.onus.Store(onuKey, onuDevice)
3000}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003001
khenaidoodc2116e2021-10-19 17:33:19 -04003002func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003003 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003004 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003005 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003006 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003007 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003008 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003009 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003010 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3011 return nil, err
3012 }
3013 ID = device.ProxyAddress.GetOnuId()
3014 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3015 valueparam.Onu = &Onu
3016 valueparam.Value = value
3017
3018 // This API is unsupported until agent patch is added
3019 resp.Unsupported = uint32(value)
3020 _ = ctx
3021
3022 // Uncomment this code once agent changes are complete and tests
3023 /*
3024 resp, err = dh.Client.GetValue(ctx, valueparam)
3025 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003026 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003027 return nil, err
3028 }
3029 */
3030
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003031 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 -08003032 return resp, nil
3033}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003034
yasin saplid0566272021-12-21 09:10:30 +00003035func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
3036 // Default to NNI
3037 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003038 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003039 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003040 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003041 }
3042 return intfID
3043}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003044
Mahir Gunyelb0046752021-02-26 13:51:05 -08003045func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
3046 dh.perPonOnuIndicationChannelLock.Lock()
3047 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3048 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003049 return ch.indicationChannel
3050 }
3051 channels := onuIndicationChannels{
3052 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08003053 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003054 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003055 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003056 stopChannel: make(chan struct{}),
3057 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003058 dh.perPonOnuIndicationChannel[intfID] = channels
3059 dh.perPonOnuIndicationChannelLock.Unlock()
3060 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003061 return channels.indicationChannel
3062
3063}
3064
Mahir Gunyelb0046752021-02-26 13:51:05 -08003065func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3066 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3067 dh.perPonOnuIndicationChannelLock.Lock()
3068 defer dh.perPonOnuIndicationChannelLock.Unlock()
3069 for _, v := range dh.perPonOnuIndicationChannel {
3070 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003071 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003072 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003073}
3074
Mahir Gunyelb0046752021-02-26 13:51:05 -08003075func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3076 ind := onuIndicationMsg{
3077 ctx: ctx,
3078 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003079 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003080 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003081 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003082 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003083}
3084
Mahir Gunyelb0046752021-02-26 13:51:05 -08003085func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003086 for {
3087 select {
3088 // process one indication per onu, before proceeding to the next one
3089 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003090 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003091 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003092 "ind": indication})
3093 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003094 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003095 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003096 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3097 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003098 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003099 }
3100 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003101 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003102 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3103 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003104 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003105 }
3106 }
3107 case <-onuChannels.stopChannel:
3108 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3109 close(onuChannels.indicationChannel)
3110 return
3111 }
3112 }
3113}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003114
3115// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3116// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003117func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003118 if dh.getDeviceDeletionInProgressFlag() {
3119 // The device itself is going to be reset as part of deletion. So nothing to be done.
3120 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3121 return nil
3122 }
3123
Girish Gowdra491a9c62021-01-06 16:43:07 -08003124 // Step1 : Fill McastFlowOrGroupControlBlock
3125 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3126 // Step3 : Wait on response channel for response
3127 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003128 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003129 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3130 errChan := make(chan error)
3131 var groupID uint32
3132 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3133 ctx: ctx,
3134 flowOrGroupAction: action,
3135 flow: flow,
3136 group: group,
3137 errChan: &errChan,
3138 }
3139 if flow != nil {
3140 groupID = flow_utils.GetGroup(flow)
3141 } else if group != nil {
3142 groupID = group.Desc.GroupId
3143 } else {
3144 return errors.New("flow-and-group-both-nil")
3145 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003146 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3147 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3148 // Derive the appropriate go routine to handle the request by a simple module operation.
3149 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3150 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3151 // Wait for handler to return error value
3152 err := <-errChan
3153 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3154 return err
3155 }
3156 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3157 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003158}
3159
3160// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003161func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003162 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003163 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003164 // block on the channel to receive an incoming mcast flow/group
3165 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003166 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3167 if mcastFlowOrGroupCb.flow != nil {
3168 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3169 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3170 log.Fields{"device-id": dh.device.Id,
3171 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003172 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3173 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3174 for _, flMgr := range dh.flowMgr {
3175 if flMgr != nil {
3176 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3177 break
3178 }
3179 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003180 // Pass the return value over the return channel
3181 *mcastFlowOrGroupCb.errChan <- err
3182 } else { // flow remove
3183 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3184 log.Fields{"device-id": dh.device.Id,
3185 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003186 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3187 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3188 for _, flMgr := range dh.flowMgr {
3189 if flMgr != nil {
3190 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3191 break
3192 }
3193 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003194 // Pass the return value over the return channel
3195 *mcastFlowOrGroupCb.errChan <- err
3196 }
3197 } else { // mcast group
3198 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3199 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3200 log.Fields{"device-id": dh.device.Id,
3201 "groupToAdd": mcastFlowOrGroupCb.group})
3202 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3203 // Pass the return value over the return channel
3204 *mcastFlowOrGroupCb.errChan <- err
3205 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3206 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3207 log.Fields{"device-id": dh.device.Id,
3208 "groupToModify": mcastFlowOrGroupCb.group})
3209 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3210 // Pass the return value over the return channel
3211 *mcastFlowOrGroupCb.errChan <- err
3212 } else { // group remove
3213 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3214 log.Fields{"device-id": dh.device.Id,
3215 "groupToRemove": mcastFlowOrGroupCb.group})
3216 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3217 // Pass the return value over the return channel
3218 *mcastFlowOrGroupCb.errChan <- err
3219 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003220 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003221 case <-stopHandler:
3222 dh.mcastHandlerRoutineActive[routineIndex] = false
3223 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003224 }
3225 }
3226}
kesavand62126212021-01-12 04:56:06 -05003227
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003228// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003229func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003230 for i, v := range dh.stopMcastHandlerRoutine {
3231 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003232 select {
3233 case v <- true:
3234 case <-time.After(time.Second * 5):
3235 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3236 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003237 }
3238 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003239
3240 if dh.incomingMcastFlowOrGroup != nil {
3241 for k := range dh.incomingMcastFlowOrGroup {
3242 if dh.incomingMcastFlowOrGroup[k] != nil {
3243 dh.incomingMcastFlowOrGroup[k] = nil
3244 }
3245 }
3246 dh.incomingMcastFlowOrGroup = nil
3247 }
3248
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003249 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003250 logger.Debug(ctx, "stopped all mcast handler routines")
3251}
3252
kesavand62126212021-01-12 04:56:06 -05003253func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3254
3255 singleValResp := extension.SingleGetValueResponse{
3256 Response: &extension.GetValueResponse{
3257 Response: &extension.GetValueResponse_PortCoutners{
3258 PortCoutners: &extension.GetOltPortCountersResponse{},
3259 },
3260 },
3261 }
3262
3263 errResp := func(status extension.GetValueResponse_Status,
3264 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3265 return &extension.SingleGetValueResponse{
3266 Response: &extension.GetValueResponse{
3267 Status: status,
3268 ErrReason: reason,
3269 },
3270 }
3271 }
3272
3273 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3274 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3275 //send error response
3276 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3277 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3278 }
3279 statIndChn := make(chan bool, 1)
3280 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3281 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3282 //request openOlt agent to send the the port statistics indication
3283
3284 go func() {
3285 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3286 if err != nil {
3287 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3288 }
3289 }()
3290 select {
3291 case <-statIndChn:
3292 //indication received for ports stats
3293 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3294 case <-time.After(oltPortInfoTimeout * time.Second):
3295 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3296 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3297 case <-ctx.Done():
3298 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3299 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3300 }
3301 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3302 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003303 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003304 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3305 cmnni := dh.portStats.collectNNIMetrics(intfID)
3306 if cmnni == nil {
3307 //TODO define the error reason
3308 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3309 }
3310 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3311 return &singleValResp
3312
3313 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3314 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003315 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003316 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3317 cmpon := dh.portStats.collectPONMetrics(intfID)
3318 if cmpon == nil {
3319 //TODO define the error reason
3320 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3321 }
3322 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3323 return &singleValResp
3324 }
3325 }
3326 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3327}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303328
3329func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3330
3331 singleValResp := extension.SingleGetValueResponse{
3332 Response: &extension.GetValueResponse{
3333 Response: &extension.GetValueResponse_OnuPonCounters{
3334 OnuPonCounters: &extension.GetOnuCountersResponse{},
3335 },
3336 },
3337 }
3338
3339 errResp := func(status extension.GetValueResponse_Status,
3340 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3341 return &extension.SingleGetValueResponse{
3342 Response: &extension.GetValueResponse{
3343 Status: status,
3344 ErrReason: reason,
3345 },
3346 }
3347 }
3348 intfID := onuPonInfo.IntfId
3349 onuID := onuPonInfo.OnuId
3350 onuKey := dh.formOnuKey(intfID, onuID)
3351
3352 if _, ok := dh.onus.Load(onuKey); !ok {
3353 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3354 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3355 }
3356 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3357 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3358 if cmnni == nil {
3359 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3360 }
3361 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3362 return &singleValResp
3363
3364}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003365
3366func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3367
3368 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3369 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3370 if err != nil {
3371 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3372 return generateSingleGetValueErrorResponse(err)
3373 }
3374 return &extension.SingleGetValueResponse{
3375 Response: &extension.GetValueResponse{
3376 Status: extension.GetValueResponse_OK,
3377 Response: &extension.GetValueResponse_RxPower{
3378 RxPower: &extension.GetRxPowerResponse{
3379 IntfId: rxPowerRequest.IntfId,
3380 OnuId: rxPowerRequest.OnuId,
3381 Status: rxPower.Status,
3382 FailReason: rxPower.FailReason.String(),
3383 RxPower: rxPower.RxPowerMeanDbm,
3384 },
3385 },
3386 },
3387 }
3388}
3389
3390func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3391 errResp := func(status extension.GetValueResponse_Status,
3392 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3393 return &extension.SingleGetValueResponse{
3394 Response: &extension.GetValueResponse{
3395 Status: status,
3396 ErrReason: reason,
3397 },
3398 }
3399 }
3400
3401 if err != nil {
3402 if e, ok := status.FromError(err); ok {
3403 switch e.Code() {
3404 case codes.Internal:
3405 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3406 case codes.DeadlineExceeded:
3407 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3408 case codes.Unimplemented:
3409 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3410 case codes.NotFound:
3411 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3412 }
3413 }
3414 }
3415
3416 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3417}
khenaidoo106c61a2021-08-11 18:05:46 -04003418
3419/*
3420Helper functions to communicate with Core
3421*/
3422
3423func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3424 cClient, err := dh.coreClient.GetCoreServiceClient()
3425 if err != nil || cClient == nil {
3426 return nil, err
3427 }
3428 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3429 defer cancel()
3430 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3431}
3432
khenaidoodc2116e2021-10-19 17:33:19 -04003433func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003434 cClient, err := dh.coreClient.GetCoreServiceClient()
3435 if err != nil || cClient == nil {
3436 return nil, err
3437 }
3438 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3439 defer cancel()
3440 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3441}
3442
khenaidoodc2116e2021-10-19 17:33:19 -04003443func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003444 cClient, err := dh.coreClient.GetCoreServiceClient()
3445 if err != nil || cClient == nil {
3446 return err
3447 }
3448 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3449 defer cancel()
3450 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3451 return err
3452}
3453
3454func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3455 cClient, err := dh.coreClient.GetCoreServiceClient()
3456 if err != nil || cClient == nil {
3457 return nil, err
3458 }
3459 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3460 defer cancel()
3461 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3462}
3463
3464func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3465 cClient, err := dh.coreClient.GetCoreServiceClient()
3466 if err != nil || cClient == nil {
3467 return nil, err
3468 }
3469 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3470 defer cancel()
3471 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3472}
3473
3474func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3475 cClient, err := dh.coreClient.GetCoreServiceClient()
3476 if err != nil || cClient == nil {
3477 return err
3478 }
3479 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3480 defer cancel()
3481 _, err = cClient.DeviceUpdate(subCtx, device)
3482 return err
3483}
3484
khenaidoodc2116e2021-10-19 17:33:19 -04003485func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003486 cClient, err := dh.coreClient.GetCoreServiceClient()
3487 if err != nil || cClient == nil {
3488 return nil, err
3489 }
3490 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3491 defer cancel()
3492 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3493}
3494
khenaidoodc2116e2021-10-19 17:33:19 -04003495func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003496 cClient, err := dh.coreClient.GetCoreServiceClient()
3497 if err != nil || cClient == nil {
3498 return err
3499 }
3500 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3501 defer cancel()
3502 _, err = cClient.SendPacketIn(subCtx, pkt)
3503 return err
3504}
3505
3506func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3507 cClient, err := dh.coreClient.GetCoreServiceClient()
3508 if err != nil || cClient == nil {
3509 return err
3510 }
3511 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3512 defer cancel()
3513 _, err = cClient.PortCreated(subCtx, port)
3514 return err
3515}
3516
khenaidoodc2116e2021-10-19 17:33:19 -04003517func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003518 cClient, err := dh.coreClient.GetCoreServiceClient()
3519 if err != nil || cClient == nil {
3520 return err
3521 }
3522 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3523 defer cancel()
3524 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3525 return err
3526}
3527
khenaidoodc2116e2021-10-19 17:33:19 -04003528func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003529 cClient, err := dh.coreClient.GetCoreServiceClient()
3530 if err != nil || cClient == nil {
3531 return err
3532 }
3533 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3534 defer cancel()
3535 _, err = cClient.PortStateUpdate(subCtx, portState)
3536 return err
3537}
3538
khenaidoodc2116e2021-10-19 17:33:19 -04003539func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003540 cClient, err := dh.coreClient.GetCoreServiceClient()
3541 if err != nil || cClient == nil {
3542 return nil, err
3543 }
3544 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3545 defer cancel()
3546 return cClient.GetDevicePort(subCtx, portFilter)
3547}
3548
3549/*
3550Helper functions to communicate with child adapter
3551*/
3552
khenaidoodc2116e2021-10-19 17:33:19 -04003553func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003554 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3555 if err != nil || aClient == nil {
3556 return err
3557 }
3558 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3559 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3560 defer cancel()
3561 _, err = aClient.OmciIndication(subCtx, response)
3562 return err
3563}
3564
khenaidoodc2116e2021-10-19 17:33:19 -04003565func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003566 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3567 if err != nil || aClient == nil {
3568 return err
3569 }
3570 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3571 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3572 defer cancel()
3573 _, err = aClient.OnuIndication(subCtx, onuInd)
3574 return err
3575}
3576
khenaidoodc2116e2021-10-19 17:33:19 -04003577func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003578 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3579 if err != nil || aClient == nil {
3580 return err
3581 }
3582 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3583 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3584 defer cancel()
3585 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3586 return err
3587}
3588
khenaidoodc2116e2021-10-19 17:33:19 -04003589func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003590 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3591 if err != nil || aClient == nil {
3592 return err
3593 }
3594 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3595 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3596 defer cancel()
3597 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3598 return err
3599}
3600
khenaidoodc2116e2021-10-19 17:33:19 -04003601func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003602 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3603 if err != nil || aClient == nil {
3604 return err
3605 }
3606 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3607 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3608 defer cancel()
3609 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3610 return err
3611}
3612
3613/*
3614Helper functions for remote communication
3615*/
3616
3617// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3618// supports is deleted
3619func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3620 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3621
3622 dh.lockChildAdapterClients.Lock()
3623 defer dh.lockChildAdapterClients.Unlock()
3624 if _, ok := dh.childAdapterClients[endpoint]; ok {
3625 // Already set
3626 return nil
3627 }
3628
3629 // Setup child's adapter grpc connection
3630 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003631 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3632 dh.cfg.AdapterEndpoint,
3633 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05003634 "onu_inter_adapter_service.OnuInterAdapterService",
3635 dh.onuInterAdapterRestarted,
3636 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003637 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3638 return err
3639 }
khenaidooefff76e2021-12-15 16:51:30 -05003640 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003641
3642 // Wait until we have a connection to the child adapter.
3643 // Unlimited retries or until context expires
3644 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3645 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3646 for {
3647 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3648 if err == nil && client != nil {
3649 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3650 break
3651 }
3652 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3653 // Backoff
3654 if err = backoff.Backoff(subCtx); err != nil {
3655 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3656 break
3657 }
3658 }
3659 return nil
3660}
3661
khenaidoodc2116e2021-10-19 17:33:19 -04003662func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003663
3664 // First check from cache
3665 dh.lockChildAdapterClients.RLock()
3666 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3667 dh.lockChildAdapterClients.RUnlock()
3668 return cgClient.GetOnuInterAdapterServiceClient()
3669 }
3670 dh.lockChildAdapterClients.RUnlock()
3671
3672 // Set the child connection - can occur on restarts
3673 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3674 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3675 cancel()
3676 if err != nil {
3677 return nil, err
3678 }
3679
3680 // Get the child client now
3681 dh.lockChildAdapterClients.RLock()
3682 defer dh.lockChildAdapterClients.RUnlock()
3683 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3684 return cgClient.GetOnuInterAdapterServiceClient()
3685 }
3686 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3687}
3688
3689func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3690 dh.lockChildAdapterClients.Lock()
3691 defer dh.lockChildAdapterClients.Unlock()
3692 for key, client := range dh.childAdapterClients {
3693 client.Stop(ctx)
3694 delete(dh.childAdapterClients, key)
3695 }
3696}
3697
khenaidooefff76e2021-12-15 16:51:30 -05003698// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
3699func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
3700 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003701 return nil
3702}
3703
khenaidooefff76e2021-12-15 16:51:30 -05003704// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
3705func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
3706 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003707 return nil
3708 }
khenaidooefff76e2021-12-15 16:51:30 -05003709 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04003710}
Girish Gowdra950326e2021-11-05 12:43:24 -07003711
3712func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3713 dh.lockDevice.Lock()
3714 defer dh.lockDevice.Unlock()
3715 dh.isDeviceDeletionInProgress = flag
3716}
3717
3718func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3719 dh.lockDevice.RLock()
3720 defer dh.lockDevice.RUnlock()
3721 return dh.isDeviceDeletionInProgress
3722}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003723
3724// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3725// Returns false if waiting timed out.
3726func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3727 c := make(chan struct{})
3728 go func() {
3729 defer close(c)
3730 wg.Wait()
3731 }()
3732 select {
3733 case <-c:
3734 return true // completed normally
3735 case <-time.After(timeout):
3736 return false // timed out
3737 }
3738}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303739
3740func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
3741 val, err := json.Marshal(signature)
3742 if err != nil {
3743 logger.Error(ctx, "failed-to-marshal")
3744 return
3745 }
3746 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
3747 logger.Error(ctx, "failed-to-store-hearbeat-signature")
3748 }
3749}
3750
3751func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
3752 var signature uint32
3753
3754 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
3755 if er == nil {
3756 if Value != nil {
3757 Val, er := kvstore.ToByte(Value.Value)
3758 if er != nil {
3759 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
3760 return signature
3761 }
3762 if er = json.Unmarshal(Val, &signature); er != nil {
3763 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
3764 return signature
3765 }
3766 }
3767 }
3768 return signature
3769}