blob: 908fb5736fc835ef3e2f575a66a623285e4c174e [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
Joey Armstrong11f5a572024-01-12 19:11:32 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
Phaneendra Manda4c62c802019-03-06 21:37:49 +05303
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Mahir Gunyela2e68702022-12-07 00:00:42 -080017// Package core provides the utility for olt devices, flows and statistics
Scott Bakerdbd960e2020-02-28 08:57:51 -080018package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053024 "encoding/json"
Girish Gowdra491a9c62021-01-06 16:43:07 -080025 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "fmt"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
Elia Battiston599d25f2022-02-16 14:49:08 +010033 "github.com/opencord/voltha-lib-go/v7/pkg/db"
34 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
35
khenaidoo106c61a2021-08-11 18:05:46 -040036 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040037
Matteo Scandolo945e4012019-12-12 14:16:11 -080038 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070039 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000040 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
41 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040042 "github.com/opencord/voltha-lib-go/v7/pkg/config"
43 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
44 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
45 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070046 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040047 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080048
nikesh.krishnand9812542023-08-01 18:31:39 +053049 grpc_retry "github.com/grpc-ecosystem/go-grpc-middleware/retry"
khenaidoo106c61a2021-08-11 18:05:46 -040050 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053051 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080052 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040053 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040054 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040055 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040056 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
57 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040058 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
59 oop "github.com/opencord/voltha-protos/v5/go/openolt"
60 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070061 "google.golang.org/grpc"
nikesh.krishnand9812542023-08-01 18:31:39 +053062 codes "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040063 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053064)
65
salmansiddiqui7ac62132019-08-22 03:58:50 +000066// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040067const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080068 InvalidPort = 0xffffffff
69 MaxNumOfGroupHandlerChannels = 256
70
71 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
72 McastFlowOrGroupModify = "McastFlowOrGroupModify"
73 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050074 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010075
76 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053077 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040078)
79
Mahir Gunyela2e68702022-12-07 00:00:42 -080080// DeviceHandler will interact with the OLT device.
Phaneendra Manda4c62c802019-03-06 21:37:49 +053081type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040082 cm *config.ConfigManager
83 device *voltha.Device
84 cfg *conf.AdapterFlags
85 coreClient *vgrpc.Client
86 childAdapterClients map[string]*vgrpc.Client
87 lockChildAdapterClients sync.RWMutex
88 EventProxy eventif.EventProxy
89 openOLT *OpenOLT
khenaidooefff76e2021-12-15 16:51:30 -050090 exitChannel chan struct{}
khenaidoo106c61a2021-08-11 18:05:46 -040091 lockDevice sync.RWMutex
92 Client oop.OpenoltClient
93 transitionMap *TransitionMap
94 clientCon *grpc.ClientConn
95 flowMgr []*OpenOltFlowMgr
96 groupMgr *OpenOltGroupMgr
97 eventMgr *OpenOltEventMgr
98 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053099 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700100
101 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530102
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700103 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
104 // if the value is true that means the OnuDiscovery indication
105 // is currently being processed and thus we can ignore concurrent requests
106 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
107 // if we do it means something went wrong and we need to retry
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700108 discOnus sync.Map
109 onus sync.Map
110 portStats *OpenOltStatisticsMgr
111 metrics *pmmetrics.PmMetrics
112 stopCollector chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000113 isCollectorActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700114 stopHeartbeatCheck chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000115 isHeartbeatCheckActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700116 activePorts sync.Map
117 stopIndications chan bool
118 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700119
Mahir Gunyelb0046752021-02-26 13:51:05 -0800120 totalPonPorts uint32
121 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
122 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800123
124 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
125 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700126 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
127 stopMcastHandlerRoutine []chan bool
128 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000129
130 adapterPreviouslyConnected bool
131 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700132
133 isDeviceDeletionInProgress bool
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530134 heartbeatSignature uint32
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700135}
136
Mahir Gunyela2e68702022-12-07 00:00:42 -0800137// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700138type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400139 deviceID string
140 deviceType string
141 serialNumber string
142 onuID uint32
143 intfID uint32
144 proxyDeviceID string
145 losRaised bool
146 rdiRaised bool
147 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700148}
149
Mahir Gunyelb0046752021-02-26 13:51:05 -0800150type onuIndicationMsg struct {
151 ctx context.Context
152 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800153}
154
155type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800156 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800157 stopChannel chan struct{}
158}
159
Mahir Gunyela2e68702022-12-07 00:00:42 -0800160// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
161// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
162// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
163// and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800164type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400165 ctx context.Context // Flow/group handler context
166 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
167 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
168 group *of.OfpGroupEntry // Group message (can be nil or valid group)
169 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800170}
171
Naga Manjunath7615e552019-10-11 22:35:47 +0530172var pmNames = []string{
173 "rx_bytes",
174 "rx_packets",
175 "rx_mcast_packets",
176 "rx_bcast_packets",
177 "tx_bytes",
178 "tx_packets",
179 "tx_mcast_packets",
180 "tx_bcast_packets",
181}
182
Mahir Gunyela2e68702022-12-07 00:00:42 -0800183// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400184func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700185 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700186 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700187 device.deviceType = deviceTp
188 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700189 device.onuID = onuID
190 device.intfID = intfID
191 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530192 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400193 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700194 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530195}
196
Mahir Gunyela2e68702022-12-07 00:00:42 -0800197// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400198func NewDeviceHandler(cc *vgrpc.Client, ep eventif.EventProxy, device *voltha.Device, adapter *OpenOLT, cm *config.ConfigManager, cfg *conf.AdapterFlags) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700199 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530200 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800201 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400202 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400203 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700204 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700205 dh.device = cloned
206 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500207 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700208 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000209 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
210 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530211 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500212 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800213 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800214 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400215 dh.childAdapterClients = make(map[string]*vgrpc.Client)
216 dh.cfg = cfg
Gustavo Silva41af9122022-10-11 11:05:13 -0300217 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, dh.cm.Backend.PathPrefix)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530218 if dh.kvStore == nil {
219 logger.Error(ctx, "Failed to setup KV store")
220 return nil
221 }
222
Girish Gowdra491a9c62021-01-06 16:43:07 -0800223 // Create a slice of buffered channels for handling concurrent mcast flow/group.
224 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700225 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
226 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800227 for i := range dh.incomingMcastFlowOrGroup {
228 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800229 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800230 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
231 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
232 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
233 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700234 dh.mcastHandlerRoutineActive[i] = true
235 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800236 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700237 //TODO initialize the support classes.
238 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530239}
240
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530241func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
242 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
243 switch storeType {
244 case "etcd":
245 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
246 }
247 return nil, errors.New("unsupported-kv-store")
248}
249
250// SetKVClient sets the KV client and return a kv backend
251func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
252 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
253 if err != nil {
254 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
255 return nil
256 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530257 kvbackend := &db.Backend{
258 Client: kvClient,
259 StoreType: backend,
260 Address: addr,
261 Timeout: rsrcMgr.KvstoreTimeout,
262 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
263
264 return kvbackend
265}
266
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000267// CloseKVClient closes open KV clients
268func (dh *DeviceHandler) CloseKVClient(ctx context.Context) {
269 if dh.resourceMgr != nil {
270 for _, rscMgr := range dh.resourceMgr {
271 if rscMgr != nil {
272 rscMgr.CloseKVClient(ctx)
273 }
274 }
275 }
276 if dh.flowMgr != nil {
277 for _, flMgr := range dh.flowMgr {
278 if flMgr != nil {
279 flMgr.CloseKVClient(ctx)
280 }
281 }
282 }
283}
284
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530285// start save the device to the data model
286func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700287 dh.lockDevice.Lock()
288 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000289 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700290 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000291 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530292}
293
khenaidooefff76e2021-12-15 16:51:30 -0500294// Stop stops the device handler
295func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700296 dh.lockDevice.Lock()
297 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000298 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500299 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400300
khenaidooefff76e2021-12-15 16:51:30 -0500301 // Delete (which will stop also) all grpc connections to the child adapters
302 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000303 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530304}
305
ssiddiqui04386ee2021-08-23 21:58:25 +0530306func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
307 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
308 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
309 if pooledIntfID == intfID {
310 return resourceRanges.GetTechnology()
311 }
312 }
313 }
314 return ""
315}
316
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400317func macifyIP(ip net.IP) string {
318 if len(ip) > 0 {
319 oct1 := strconv.FormatInt(int64(ip[12]), 16)
320 oct2 := strconv.FormatInt(int64(ip[13]), 16)
321 oct3 := strconv.FormatInt(int64(ip[14]), 16)
322 oct4 := strconv.FormatInt(int64(ip[15]), 16)
323 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
324 }
325 return ""
326}
327
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400329 var genmac string
330 var addr net.IP
331 var ips []string
332 var err error
333
Neha Sharma96b7bf22020-06-15 10:37:32 +0000334 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400335
336 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000337 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400338
339 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000340 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400341 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000342 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400343 }
344 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000345 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530346 log.Fields{"host": ips[0],
347 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400348 return genmac, nil
349 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000350 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400351 }
352
353 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000354 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530355 log.Fields{"host": host,
356 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400357 return genmac, nil
358}
359
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530360func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700361 slist := strings.Split(mac, ":")
362 result := make([]uint32, len(slist))
363 var err error
364 var tmp int64
365 for index, val := range slist {
366 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
367 return []uint32{1, 2, 3, 4, 5, 6}
368 }
369 result[index] = uint32(tmp)
370 }
371 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530372}
373
Mahir Gunyela2e68702022-12-07 00:00:42 -0800374// GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800375func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530376
David K. Bainbridge794735f2020-02-11 21:01:37 -0800377 switch portType {
378 case voltha.Port_ETHERNET_NNI:
379 return fmt.Sprintf("nni-%d", portNum), nil
380 case voltha.Port_PON_OLT:
381 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700382 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800383
Girish Kumarf26e4882020-03-05 06:49:10 +0000384 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530385}
386
Elia Battiston596406d2022-02-02 12:19:00 +0100387func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
388 if speedMbps == 0 {
389 //In case it was not set in the indication
390 //and no other value was provided
391 speedMbps = defaultPortSpeedMbps
392 }
393
394 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
395 switch speedMbps {
396 case 1000000:
397 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
398 case 100000:
399 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
400 case 40000:
401 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
402 case 10000:
403 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
404 case 1000:
405 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
406 case 100:
407 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
408 case 10:
409 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
410 }
411
412 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
413
414 port := &of.OfpPort{
415 HwAddr: macAddressToUint32Array(macAddress),
416 Config: 0,
417 State: uint32(of.OfpPortState_OFPPS_LIVE),
418 Curr: capacity,
419 Advertised: capacity,
420 Peer: capacity,
421 CurrSpeed: speedMbps * 1000, //kbps
422 MaxSpeed: speedMbps * 1000, //kbps
423 }
424
425 return port
426}
427
428func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000429 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700430 if state == "up" {
431 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500432 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500433 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700434 } else {
435 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500436 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700437 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700438 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400439 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800440 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000441 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400442 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500443
khenaidoo106c61a2021-08-11 18:05:46 -0400444 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400445 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400446 DeviceId: dh.device.Id,
447 Port: portNum,
448 })
449 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000450 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400451 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400452 DeviceId: dh.device.Id,
453 PortType: portType,
454 PortNo: portNum,
455 OperStatus: operStatus})
456 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400457 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
458 "device-id": dh.device.Id,
459 "port-type": portType,
460 "port-number": portNum,
461 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500462 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400463 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500464 }
khenaidoo106c61a2021-08-11 18:05:46 -0400465
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400466 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400467 port = &voltha.Port{
468 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700469 PortNo: portNum,
470 Label: label,
471 Type: portType,
472 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100473 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700474 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000475 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700476 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400477 err = dh.createPortInCore(ctx, port)
478 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000479 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800480 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000481 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400482 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000483 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530484 return nil
485}
486
Kent Hagermane6ff1012020-07-14 15:07:53 -0400487func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400488 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530489 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400490 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
491 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530492 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800493 dh.lockDevice.Lock()
494 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530495 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530496}
497
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700498// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530499// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800500func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000501 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700502 defer func() {
503 dh.lockDevice.Lock()
504 dh.isReadIndicationRoutineActive = false
505 dh.lockDevice.Unlock()
506 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700507 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700508 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700509 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700510 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400511
David Bainbridgef5879ca2019-12-13 21:17:54 +0000512 // Create an exponential backoff around re-enabling indications. The
513 // maximum elapsed time for the back off is set to 0 so that we will
514 // continue to retry. The max interval defaults to 1m, but is set
515 // here for code clarity
516 indicationBackoff := backoff.NewExponentialBackOff()
517 indicationBackoff.MaxElapsedTime = 0
518 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700519
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700520 dh.lockDevice.Lock()
521 dh.isReadIndicationRoutineActive = true
522 dh.lockDevice.Unlock()
523
Girish Gowdra3f974912020-03-23 20:35:18 -0700524Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700525 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400526 select {
527 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000528 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700529 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400530 default:
531 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100532
533 select {
534 case <-indications.Context().Done():
535 if err != nil {
536 logger.Warnw(ctx, "error-during-enable-indications",
537 log.Fields{"err": err,
538 "device-id": dh.device.Id})
539 }
540
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400541 // Use an exponential back off to prevent getting into a tight loop
542 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100543 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
544 "device-id": dh.device.Id,
545 "duration": duration,
546 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400547 if duration == backoff.Stop {
548 // If we reach a maximum then warn and reset the backoff
549 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100550 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530551 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530552 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400553 indicationBackoff.Reset()
554 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700555
556 // On failure process a backoff timer while watching for stopIndications
557 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700558 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700559 select {
560 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000561 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700562 if !backoffTimer.Stop() {
563 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700564 }
565 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700566 case <-backoffTimer.C:
567 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700568 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700569 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
570 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400571 }
572 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100573 default:
574 if err != nil {
575 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530576 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530577 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100578 // Close the stream, and re-initialize it
579 if err = indications.CloseSend(); err != nil {
580 // Ok to ignore here, because we landed here due to a problem on the stream
581 // In all probability, the closeSend call may fail
582 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
583 log.Fields{"err": err,
584 "device-id": dh.device.Id})
585 }
586 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
587 return err
588 }
589 // once we re-initialized the indication stream, continue to read indications
590 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700591 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100592 // Reset backoff if we have a successful receive
593 indicationBackoff.Reset()
594 // When OLT is admin down, ignore all indications.
595 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
596 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
597 log.Fields{"indication": indication,
598 "device-id": dh.device.Id})
599 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700600 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100601 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530602 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700603 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700604 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700605 // Close the send stream
606 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700607
Girish Gowdra3f974912020-03-23 20:35:18 -0700608 return nil
609}
610
611func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700612 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700613 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
614 if err != nil {
615 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
616 }
617 if indications == nil {
618 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
619 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700620 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700621 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400622}
623
624// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
625func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
626 switch indication.Data.(type) {
627 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
628 return true
629
630 default:
631 return false
632 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633}
634
David K. Bainbridge794735f2020-02-11 21:01:37 -0800635func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700636 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000637 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530638 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700639 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530640 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700641 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000642 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000643 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530644 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000645 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800646 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000647 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800648 }
649 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650}
651
David K. Bainbridge794735f2020-02-11 21:01:37 -0800652// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530653func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700654 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 switch indication.Data.(type) {
656 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000657 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
658 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700659 logger.Infow(ctx, "received olt indication", log.Fields{"device-id": dh.device.Id, "olt-ind": indication.GetOltInd()})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800660 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400661 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800662 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700663 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000664 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
665 defer span.Finish()
666
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700667 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800668 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100669 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400670 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 }
672 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000673 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700674 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000675 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
676 defer span.Finish()
677
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700678 intfOperInd := indication.GetIntfOperInd()
679 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800680 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100681 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400682 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800683 }
684 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700685 } else if intfOperInd.GetType() == "pon" {
686 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
687 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800688 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100689 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400690 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800691 }
692 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000693 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700694 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000695 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530696 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530697 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700698 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000699 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
700 defer span.Finish()
701
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700702 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000703 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800704 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800705 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700706 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000707 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
708 defer span.Finish()
709
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000711 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800712 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800713 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700714 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000715 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
716 defer span.Finish()
717
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700718 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000719 logger.Debugw(ctx, "received-omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800720 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000721 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400722 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800723 }
724 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700725 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000726 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
727 defer span.Finish()
728
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700729 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000730 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700731 "intf-type": pktInd.IntfId,
732 "intf-id": pktInd.IntfId,
733 "gem-port-id": pktInd.GemportId,
734 "port-no": pktInd.PortNo,
735 "device-id": dh.device.Id,
736 })
737
738 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000739 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700740 "intf-type": pktInd.IntfId,
741 "intf-id": pktInd.IntfId,
742 "gem-port-id": pktInd.GemportId,
743 "port-no": pktInd.PortNo,
744 "packet": hex.EncodeToString(pktInd.Pkt),
745 "device-id": dh.device.Id,
746 })
747 }
748
David K. Bainbridge794735f2020-02-11 21:01:37 -0800749 go func() {
750 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400751 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800752 }
753 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700754 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000755 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
756 defer span.Finish()
757
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700758 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700759 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700760 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000761 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
762 defer span.Finish()
763
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700764 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000765 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700766 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000767 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
768 defer span.Finish()
769
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700770 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000771 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
772 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700773 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530774}
775
nikesh.krishnanc8473432023-06-14 12:14:54 +0530776func generateOnuIndication(intfID, onuID uint32, operState, adminState string) *oop.Indication {
777 onuInd := &oop.OnuIndication{
778 IntfId: intfID,
779 OnuId: onuID,
780 OperState: operState,
781 AdminState: adminState,
782 }
783 indication := &oop.Indication{
784 Data: &oop.Indication_OnuInd{
785 OnuInd: onuInd,
786 },
787 }
788 return indication
789}
790
791func generateOnuAlarmIndication(intfID uint32, onuID uint32, losStatus string) *oop.AlarmIndication {
792 onuAlarmInd := &oop.OnuAlarmIndication{
793 IntfId: intfID,
794 OnuId: onuID,
795 LosStatus: losStatus,
796 }
797 alarmInd := &oop.AlarmIndication{
798 Data: &oop.AlarmIndication_OnuAlarmInd{
799 OnuAlarmInd: onuAlarmInd,
800 },
801 }
802 return alarmInd
803}
804func generatePonLosAlarmIndication(intfID uint32, losStatus string) *oop.AlarmIndication {
805
806 ponlosAlarmInd := &oop.LosIndication{
807 IntfId: intfID,
808 Status: losStatus,
809 }
810 alarmInd := &oop.AlarmIndication{
811 Data: &oop.AlarmIndication_LosInd{
812 LosInd: ponlosAlarmInd,
813 },
814 }
815 return alarmInd
816}
817func (dh *DeviceHandler) updateIntfOperStateAndRaiseIndication(ctx context.Context, operState string, intfID uint32) {
818 go func() {
819 if err := dh.addPort(ctx, intfID, voltha.Port_PON_OLT, operState, defaultPortSpeedMbps); err != nil {
820 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
821 }
822 }()
823
824 raisedTs := time.Now().Unix()
825 go dh.eventMgr.oltIntfOperIndication(ctx, &oop.IntfOperIndication{Type: "pon", IntfId: intfID, OperState: operState}, dh.device.Id, raisedTs)
826}
827
828func (dh *DeviceHandler) reconcileOnus(ctx context.Context) error {
829
830 onuDevicesFromCore, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
831 if err != nil {
832
833 logger.Error(ctx, "unable to fetch child device", log.Fields{"eeror": err})
834
835 return err
836 }
837 for _, onuDeviceFromCore := range onuDevicesFromCore.Items {
838
839 onuOperStatusFromCore := onuDeviceFromCore.OperStatus
840 onuConnectStatusFromCore := onuDeviceFromCore.ConnectStatus
841 intfID := plt.PortNoToIntfID(onuDeviceFromCore.ParentPortNo, voltha.Port_PON_OLT)
842
843 onuID := onuDeviceFromCore.ProxyAddress.OnuId
844 onuDeviceFromOlt, err := dh.getOnuInfo(ctx, intfID, &onuID)
845 if err != nil {
846 logger.Error(ctx, "unable to get onu object from olt agent", log.Fields{"eeror": err})
847
848 } else {
849 onuOperStatusFromOlt := onuDeviceFromOlt.GetState()
850 onuLosFromOlt := onuDeviceFromOlt.GetLosi()
851 switch {
852 case onuOperStatusFromOlt.String() == "ACTIVE" && onuOperStatusFromCore.String() != "ACTIVE":
853 OnuIndication := generateOnuIndication(intfID, onuID, "up", "up")
854 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
855
856 case onuLosFromOlt.String() == "ON" && onuConnectStatusFromCore.String() == "REACHABLE":
857 OnuIndication := generateOnuIndication(intfID, onuID, "down", "down") //check bal cli login notepad
858 alarmInd := generateOnuAlarmIndication(intfID, onuID, "on")
859 raisedTs := time.Now().Unix()
860 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
861
862 dh.putOnuIndicationToChannel(ctx, OnuIndication, intfID)
863 }
864
865 }
866
867 }
868
869 return nil
870}
871
872func (dh *DeviceHandler) reconcilePonPorts(ctx context.Context) error { // need onuid and pon id
873 portsFromCore, err := dh.getAllPortsFromCore(ctx, &ca.PortFilter{
874 DeviceId: dh.device.Id,
875 PortType: voltha.Port_PON_OLT,
876 })
877 if err != nil {
878 logger.Error(ctx, "unable to fetch ports from core", log.Fields{"eeror": err})
879
880 return err
881
882 }
883 for _, portFromCore := range portsFromCore.Items {
884 portNum := portFromCore.GetPortNo()
885 intfID := plt.PortNoToIntfID(portNum, voltha.Port_PON_OLT)
886 portOperStatusFromCore := portFromCore.OperStatus
887 portAdminStateFromCore := portFromCore.AdminState
888 ponPortFromOlt, err := dh.getIntfInfo(ctx, intfID)
889 if err != nil {
890 logger.Error(ctx, "unable to get pon objects from olt agent", log.Fields{"eeror": err})
891 } else {
892 portLosFromOlt := ponPortFromOlt.GetLos()
893 portStateFromOlt := ponPortFromOlt.GetState()
894 if portOperStatusFromCore.String() == "ACTIVE" && portLosFromOlt.String() == "ON" {
895 logger.Debug(ctx, "port is active in core but los is fired from olt", log.Fields{
896 "portStateFromOlt": portStateFromOlt.String(),
897 "portOperStatusFromCore": portOperStatusFromCore.String(),
898 "device-id": dh.device.Id,
899 "port": portNum})
900 ponLosindication := generatePonLosAlarmIndication(intfID, "on")
901 raisedTs := time.Now().Unix()
902 go dh.eventMgr.ProcessEvents(ctx, ponLosindication, dh.device.Id, raisedTs)
903
904 }
905 switch {
906 case portStateFromOlt.String() == "ACTIVE_WORKING" && portOperStatusFromCore.String() != "ACTIVE":
907 logger.Debug(ctx, "mismatch between port state in voltha core and raising port up event", log.Fields{
908 "portStateFromOlt": portStateFromOlt.String(),
909 "portOperStatusFromCore": portOperStatusFromCore.String(),
910 "device-id": dh.device.Id,
911 "port": portNum})
912 dh.updateIntfOperStateAndRaiseIndication(ctx, "up", intfID)
913 case (portStateFromOlt.String() == "INACTIVE" || portStateFromOlt.String() == "UNKNOWN") && portOperStatusFromCore.String() == "ACTIVE":
914 logger.Debug(ctx, "mismatch between port state in voltha core and raising port down event", log.Fields{
915 "portStateFromOlt": portStateFromOlt.String(),
916 "portOperStatusFromCore": portOperStatusFromCore.String(),
917 "device-id": dh.device.Id,
918 "port": portNum})
919 dh.updateIntfOperStateAndRaiseIndication(ctx, "down", intfID)
920 case portStateFromOlt.String() == "DISABLED" && portAdminStateFromCore.String() == "ENABLED":
921 logger.Error(ctx, "port enabled in device but disabled at votlha core", log.Fields{
922 "device-id": dh.device.Id,
923 "port": portNum})
924 default:
925 logger.Error(ctx, "mismatch between port state in voltha core and voltha device", log.Fields{
926 "portStateFromOlt": portStateFromOlt.String(),
927 "portOperStatusFromCore": portOperStatusFromCore.String(),
928 "device-id": dh.device.Id,
929 "port": portNum})
930
931 }
932
933 }
934
935 }
936
937 return nil
938}
939
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530940// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530941func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530942 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000943 go startCollector(ctx, dh)
nikesh.krishnanc8473432023-06-14 12:14:54 +0530944 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
945 if err == nil {
946 if device.OperStatus == voltha.OperStatus_RECONCILING {
947 err = dh.reconcileOnus(ctx)
948 if err != nil {
949 logger.Error(ctx, "unable to reconcile onu", log.Fields{"eeror": err})
950 }
951 err = dh.reconcilePonPorts(ctx)
952 if err != nil {
953 logger.Error(ctx, "unable to reconcile pon ports", log.Fields{"eeror": err})
954 }
955 }
956 }
Girish Gowdra618fa572021-09-01 17:19:29 -0700957 // instantiate the mcast handler routines.
958 for i := range dh.incomingMcastFlowOrGroup {
959 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
960 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
961 if !dh.mcastHandlerRoutineActive[i] {
962 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
963 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
964 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
965 // for incoming mcast flow/group to be processed serially.
966 dh.mcastHandlerRoutineActive[i] = true
967 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
968 }
969 }
970
Girish Gowdru0c588b22019-04-23 23:24:56 -0400971 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400972 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400973 DeviceId: dh.device.Id,
974 OperStatus: voltha.OperStatus_ACTIVE,
975 ConnStatus: voltha.ConnectStatus_REACHABLE,
976 }); err != nil {
977 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400978 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000979
980 //Clear olt communication failure event
981 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
982 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700983 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000984 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
985
Girish Gowdru0c588b22019-04-23 23:24:56 -0400986 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530987}
988
989// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530990func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000991 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400992
khenaidoo106c61a2021-08-11 18:05:46 -0400993 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400994 if err != nil || device == nil {
995 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000996 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400997 }
998
999 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -04001000
1001 //Update the device oper state and connection status
1002 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001003 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001004 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001005 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -04001006
khenaidoodc2116e2021-10-19 17:33:19 -04001007 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001008 DeviceId: cloned.Id,
1009 OperStatus: cloned.OperStatus,
1010 ConnStatus: cloned.ConnectStatus,
1011 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001012 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001013 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001014
1015 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001016 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001017 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001018 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001019 }
1020 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001021 // Update onu state as down in onu adapter
1022 onuInd := oop.OnuIndication{}
1023 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -04001024
1025 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
1026 if err != nil {
1027 return err
1028 }
1029 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -04001030 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001031 DeviceId: onuDevice.Id,
1032 OnuIndication: &onuInd,
1033 })
1034 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001035 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001036 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001037 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001038 "onu-indicator": onuInd,
1039 "device-type": onuDevice.Type,
1040 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -07001041 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001042 } else {
1043 logger.Debugw(ctx, "sending inter adapter down ind to onu success", log.Fields{"olt-device-id": device.Id, "onu-device-id": onuDevice.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001044 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001045 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001046 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -07001047 /* Discovered ONUs entries need to be cleared , since after OLT
1048 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301049 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -08001050 dh.lockDevice.Unlock()
1051
Neha Sharma96b7bf22020-06-15 10:37:32 +00001052 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001053 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301054}
1055
1056// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +05301057func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001058 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +00001059
1060 // if the connection is already available, close the previous connection (olt reboot case)
1061 if dh.clientCon != nil {
1062 if err = dh.clientCon.Close(); err != nil {
1063 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
1064 } else {
1065 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
1066 }
1067 }
1068
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301069 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +00001070 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +00001071 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
1072 grpc.WithInsecure(),
1073 grpc.WithBlock(),
1074 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001075 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001076 )),
1077 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +00001078 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +00001079 )))
1080
1081 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301082 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301083 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001084 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001085 }
Akash Sonif49299a2024-04-25 12:06:37 +05301086 //Setting oper and connection state to RECONCILING and conn state to reachable
1087 cgClient, err := dh.coreClient.GetCoreServiceClient()
1088 if err != nil {
1089 return err
1090 }
1091
1092 if dh.device.OperStatus == voltha.OperStatus_RECONCILING {
1093 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.rpcTimeout)
1094 defer cancel()
1095 if _, err := cgClient.DeviceStateUpdate(subCtx, &ca.DeviceStateFilter{
1096 DeviceId: dh.device.Id,
1097 OperStatus: voltha.OperStatus_RECONCILING,
1098 ConnStatus: voltha.ConnectStatus_REACHABLE,
1099 }); err != nil {
1100 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
1101 }
1102 // The OperState and connection state of the device is set to RECONCILING and REACHABLE in the previous section. This also needs to be set on the
1103 // locally cached copy of the device struct.
1104 dh.device.OperStatus = voltha.OperStatus_RECONCILING
1105 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
1106 }
1107
Girish Gowdru0c588b22019-04-23 23:24:56 -04001108 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301109}
1110
1111// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +05301112func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001113 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +05301114 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001115 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301116}
1117
1118// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +05301119func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301120 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +00001121 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001122
1123 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -04001124 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +05301125 if err != nil || device == nil {
1126 /*TODO: needs to handle error scenarios */
1127 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1128 }
1129 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001130 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001131
1132 cloned := proto.Clone(device).(*voltha.Device)
1133 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
1134 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1135 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001136
khenaidoodc2116e2021-10-19 17:33:19 -04001137 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001138 DeviceId: cloned.Id,
1139 OperStatus: cloned.OperStatus,
1140 ConnStatus: cloned.ConnectStatus,
1141 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301142 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 -04001143 }
1144
Chaitrashree G S44124192019-08-07 20:21:36 -04001145 // 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 +05301146 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001147 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301148 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001149 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001150 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
1151 // all the modules initialized and ready to handle incoming ONUs.
1152
Thomas Lee S985938d2020-05-04 11:40:41 +05301153 err = dh.initializeDeviceHandlerModules(ctx)
1154 if err != nil {
1155 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 -04001156 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001157
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001158 go startHeartbeatCheck(ctx, dh)
1159
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001160 return nil
1161 }
1162
khenaidoo106c61a2021-08-11 18:05:46 -04001163 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001164 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -04001165 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001166 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001167 }
khenaidoo106c61a2021-08-11 18:05:46 -04001168 dh.populateActivePorts(ctx, ports.Items)
1169 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001170 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -04001171 }
1172
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001173 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301174 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 -04001175 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301176
Neha Sharma96b7bf22020-06-15 10:37:32 +00001177 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001178
1179 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001180 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001181 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001182
1183 go startHeartbeatCheck(ctx, dh)
1184
cuilin20187b2a8c32019-03-26 19:52:28 -07001185 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301186}
1187
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001188func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001189 var err error
1190 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001191
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00001192 if dh.flowMgr != nil {
1193 dh.StopAllFlowRoutines(ctx)
1194 }
1195
1196 dh.CloseKVClient(ctx)
1197
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001198 if err != nil {
1199 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
1200 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001201 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
1202 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +00001203 // +1 is for NNI
1204 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
1205 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001206 var i uint32
yasin saplid0566272021-12-21 09:10:30 +00001207 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
1208 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
1209 // There is only one NNI manager since multiple NNI is not supported for now
1210 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001211 // Instantiate resource manager
1212 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 -07001213 return olterrors.ErrResourceManagerInstantiating
1214 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001215 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001216 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
1217 // the KV store to manage mcast group data. Provide the first instance (0th index)
1218 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
1219 return olterrors.ErrGroupManagerInstantiating
1220 }
yasin saplid0566272021-12-21 09:10:30 +00001221 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001222 // Instantiate flow manager
1223 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001224 //Continue to check the rest of the ports
1225 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1226 } else {
1227 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001228 }
1229 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001230 /* TODO: Instantiate Alarm , stats , BW managers */
1231 /* Instantiating Event Manager to handle Alarms and KPIs */
1232 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1233
1234 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001235 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001236
1237 return nil
1238
1239}
1240
Neha Sharma96b7bf22020-06-15 10:37:32 +00001241func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001242 var err error
1243 var deviceInfo *oop.DeviceInfo
1244
Neha Sharma8f4e4322020-08-06 10:51:53 +00001245 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001246
1247 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001248 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001249 }
1250 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001251 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001252 }
1253
Neha Sharma96b7bf22020-06-15 10:37:32 +00001254 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001255 dh.device.Root = true
1256 dh.device.Vendor = deviceInfo.Vendor
1257 dh.device.Model = deviceInfo.Model
1258 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1259 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1260 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1261
1262 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001263 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001264 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001265 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001266 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001267 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001268 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001269 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001270 dh.device.MacAddress = genmac
1271 } else {
1272 dh.device.MacAddress = deviceInfo.DeviceId
1273 }
1274
1275 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001276 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001277 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001278 }
1279
1280 return deviceInfo, nil
1281}
1282
Neha Sharma96b7bf22020-06-15 10:37:32 +00001283func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001284 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001285
1286 defer func() {
1287 dh.lockDevice.Lock()
1288 dh.isCollectorActive = false
1289 dh.lockDevice.Unlock()
1290 }()
1291
1292 dh.lockDevice.Lock()
1293 dh.isCollectorActive = true
1294 dh.lockDevice.Unlock()
1295
Naga Manjunath7615e552019-10-11 22:35:47 +05301296 for {
1297 select {
1298 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001299 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301300 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001301 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001302
khenaidoo106c61a2021-08-11 18:05:46 -04001303 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001304 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001305 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001306 continue
1307 }
khenaidoo106c61a2021-08-11 18:05:46 -04001308 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301309 // NNI Stats
1310 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001311 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301312 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001313 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001314 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001315 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301316 }
1317 // PON Stats
1318 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001319 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301320 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1321 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001322 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001323 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301324 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001325 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001326
yasin sapli9e4c5092022-02-01 13:52:33 +00001327 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001328 if len(onuGemInfoLst) > 0 {
1329 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001330 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001331 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301332 }
1333 }
1334 }
1335}
1336
Mahir Gunyela2e68702022-12-07 00:00:42 -08001337// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301338func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001339 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001340 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301341 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301342
1343 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001344 cgClient, err := dh.coreClient.GetCoreServiceClient()
1345 if err != nil {
1346 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1347 return
1348 }
1349
1350 // Now, set the initial PM configuration for that device
1351 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001352 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301353 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301354}
1355
Mahir Gunyela2e68702022-12-07 00:00:42 -08001356// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001357func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1358 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001359 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301360 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001361 HwDesc: "open_pon",
1362 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001363 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001364 },
1365 SwitchFeatures: &of.OfpSwitchFeatures{
1366 NBuffers: 256,
1367 NTables: 2,
1368 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1369 of.OfpCapabilities_OFPC_TABLE_STATS |
1370 of.OfpCapabilities_OFPC_PORT_STATS |
1371 of.OfpCapabilities_OFPC_GROUP_STATS),
1372 },
1373 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301374}
1375
khenaidoo106c61a2021-08-11 18:05:46 -04001376// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001377func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001378 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001379 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001380 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001381 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001382 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1383 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()
1384 }
khenaidoo106c61a2021-08-11 18:05:46 -04001385 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Mahir Gunyela2e68702022-12-07 00:00:42 -08001386
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001387}
1388
Neha Sharma96b7bf22020-06-15 10:37:32 +00001389func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001390 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 -07001391 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001392 var deviceID string
1393 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001394 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001395
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001396 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001397 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001398 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 -07001399 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1400 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001401
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001402 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301403
1404 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1405
Neha Sharma96b7bf22020-06-15 10:37:32 +00001406 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 -07001407 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001408
khenaidoodc2116e2021-10-19 17:33:19 -04001409 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001410 ParentId: dh.device.Id,
1411 OnuId: omciInd.OnuId,
1412 ParentPortNo: ponPort,
1413 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001414 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301415 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001416 "intf-id": omciInd.IntfId,
1417 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001418 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001419 deviceType = onuDevice.Type
1420 deviceID = onuDevice.Id
1421 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001422 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001423 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001424 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001425 } else {
1426 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001427 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 +05301428 deviceType = onuInCache.(*OnuDevice).deviceType
1429 deviceID = onuInCache.(*OnuDevice).deviceID
1430 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001431 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001432 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001433
khenaidoodc2116e2021-10-19 17:33:19 -04001434 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001435 ParentDeviceId: proxyDeviceID,
1436 ChildDeviceId: deviceID,
1437 Message: omciInd.Pkt,
1438 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301439 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001440 "source": dh.openOLT.config.AdapterEndpoint,
1441 "device-type": deviceType,
1442 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001443 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001444 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001445 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001446 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301447}
1448
khenaidoo106c61a2021-08-11 18:05:46 -04001449// //ProcessInterAdapterMessage sends the proxied messages to the target device
1450// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1451// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001452// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001453// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001454// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001455// return dh.handleInterAdapterOmciMsg(ctx, msg)
1456// }
1457// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1458// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001459
kesavandb9f54fd2021-11-25 20:08:04 +05301460// ProxyOmciRequests sends the proxied OMCI message to the target device
1461func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301462 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1463 return status.Error(codes.Unavailable, "OLT unreachable")
1464 }
kesavandb9f54fd2021-11-25 20:08:04 +05301465 if omciMsgs.GetProxyAddress() == nil {
1466 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1467 if err != nil {
1468 return olterrors.NewErrNotFound("onu", log.Fields{
1469 "parent-device-id": dh.device.Id,
1470 "child-device-id": omciMsgs.ChildDeviceId}, err)
1471 }
1472 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1473 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1474 return olterrors.NewErrCommunication("send-failed", log.Fields{
1475 "parent-device-id": dh.device.Id,
1476 "child-device-id": omciMsgs.ChildDeviceId}, err)
1477 }
1478 } else {
1479 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1480 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1481 return olterrors.NewErrCommunication("send-failed", log.Fields{
1482 "parent-device-id": dh.device.Id,
1483 "child-device-id": omciMsgs.ChildDeviceId}, err)
1484 }
1485 }
1486 return nil
1487}
1488
1489func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1490 var intfID uint32
1491 var onuID uint32
1492 var connectStatus common.ConnectStatus_Types
1493 if onuDevice != nil {
1494 intfID = onuDevice.ProxyAddress.GetChannelId()
1495 onuID = onuDevice.ProxyAddress.GetOnuId()
1496 connectStatus = onuDevice.ConnectStatus
1497 } else {
1498 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1499 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1500 connectStatus = omciMsgs.GetConnectStatus()
1501 }
1502 if connectStatus != voltha.ConnectStatus_REACHABLE {
1503 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1504
1505 return olterrors.NewErrCommunication("unreachable", log.Fields{
1506 "intf-id": intfID,
1507 "onu-id": onuID}, nil)
1508 }
1509
1510 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1511 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1512
1513 onuSecOmciMsgList := omciMsgs.GetMessages()
1514
1515 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1516
1517 var omciMessage *oop.OmciMsg
1518 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1519 hex.Encode(hexPkt, onuSecOmciMsg)
1520 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1521
1522 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1523 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1524 //https://jira.opencord.org/browse/VOL-4604
1525 transid := extractOmciTransactionID(onuSecOmciMsg)
1526 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1527 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1528
1529 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1530 if err != nil {
1531 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1532 "intf-id": intfID,
1533 "onu-id": onuID,
1534 "message": omciMessage}, err)
1535 }
1536 }
1537 return nil
1538}
1539
khenaidoo106c61a2021-08-11 18:05:46 -04001540// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001541func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001542 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 -07001543
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301544 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1545 return status.Error(codes.Unavailable, "OLT unreachable")
1546 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001547 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001548 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001549 if err != nil {
1550 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001551 "parent-device-id": dh.device.Id,
1552 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001553 }
khenaidoo106c61a2021-08-11 18:05:46 -04001554 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1555 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001556 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001557 "parent-device-id": dh.device.Id,
1558 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001559 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001560 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001561 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1562 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001563 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001564 "parent-device-id": dh.device.Id,
1565 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001566 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001567 }
1568 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301569}
1570
khenaidoodc2116e2021-10-19 17:33:19 -04001571func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001572 var intfID uint32
1573 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001574 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001575 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001576 intfID = onuDevice.ProxyAddress.GetChannelId()
1577 onuID = onuDevice.ProxyAddress.GetOnuId()
1578 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001579 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001580 intfID = omciMsg.GetProxyAddress().GetChannelId()
1581 onuID = omciMsg.GetProxyAddress().GetOnuId()
1582 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001583 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001584 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001585 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 -08001586
Thomas Lee S94109f12020-03-03 16:39:29 +05301587 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001588 "intf-id": intfID,
1589 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001590 }
1591
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001592 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1593 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301594 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001595 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001596 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1597 hex.Encode(hexPkt, omciMsg.Message)
1598 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1599
1600 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1601 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1602 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001603 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001604 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001605
Neha Sharma8f4e4322020-08-06 10:51:53 +00001606 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001607 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301608 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001609 "intf-id": intfID,
1610 "onu-id": onuID,
1611 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001612 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001613 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001614}
1615
David K. Bainbridge794735f2020-02-11 21:01:37 -08001616func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301617 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 +00001618 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001619 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001620 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001621 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301622 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301623 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001624 st, _ := status.FromError(err)
1625 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001626 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1627
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001628 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301629 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001630 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001631 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001632 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001633 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001634 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001635}
1636
Mahir Gunyela2e68702022-12-07 00:00:42 -08001637// getChildDevice function can be used in general to get child device, if not found in cache the function will
1638// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301639func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1640 var InCacheOnuDev *OnuDevice
1641 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1642 if onuInCache.(*OnuDevice).serialNumber == sn {
1643 InCacheOnuDev = onuInCache.(*OnuDevice)
1644 return false
1645 }
1646 return true
1647 })
1648 //Got the onu device from cache return
1649 if InCacheOnuDev != nil {
1650 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1651 return InCacheOnuDev
1652 }
1653 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1654 ParentId: dh.device.Id,
1655 SerialNumber: sn,
1656 ParentPortNo: parentPortNo,
1657 })
1658 //No device found in core return nil
1659 if onuDevice == nil {
1660 return nil
1661 }
1662 onuID := onuDevice.ProxyAddress.OnuId
1663 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1664 onuKey := dh.formOnuKey(intfID, onuID)
1665
1666 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1667 dh.onus.Store(onuKey, onuDev)
1668 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1669 return onuDev
1670}
1671
1672func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001673 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001674 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301675 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001676
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301677 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1678 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1679 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1680 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1681 if onuDev != nil {
1682 var onuGemInfo *rsrcMgr.OnuGemInfo
1683 var err error
1684 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1685 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1686 return false, err
1687 }
1688 if onuGemInfo != nil {
1689 for _, uni := range onuGemInfo.UniPorts {
1690 uniID := plt.UniIDFromPortNum(uni)
1691 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1692 if len(tpIDs) != 0 {
1693 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1694 tpInstExists = true
1695 break
1696 }
1697 }
1698 }
1699 }
1700 return tpInstExists, nil
1701 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301702
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301703 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1704 ParentId: dh.device.Id,
1705 SerialNumber: sn,
1706 ParentPortNo: parentPortNo,
1707 })
1708 if onuDevice != nil {
1709 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1710 return true, nil
1711 }
1712 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1713
1714 return false, nil
1715
1716}
1717
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001718// processDiscONULOSClear clears the LOS Alarm if it's needed
1719func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301720 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001721 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301722
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001723 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1724 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1725 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1726 OnuLosRaise event sent for it */
1727 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1728 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1729 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1730 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1731 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1732 "currentIntfId": onuDiscInd.GetIntfId()})
1733 // TODO:: Should we need to ignore raising OnuLosClear event
1734 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301735 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001736 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1737 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1738 alarmInd.LosStatus = statusCheckOff
1739 go func() {
1740 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1741 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1742 }
1743 }()
1744 // stop iterating
1745 return false
1746 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301747 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001748 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301749}
1750
1751func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301752 var error error
1753
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301754 channelID := onuDiscInd.GetIntfId()
1755 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1756
1757 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301758 defer func() {
1759 if error != nil {
1760 logger.Infow(ctx, "onu-processing-errored-out-not-adding-to-discovery-map", log.Fields{"sn": sn})
1761 } else {
1762 // once the function completes set the value to false so that
1763 // we know the processing has inProcess.
1764 // Note that this is done after checking if we are already processing
1765 // to avoid changing the value from a different thread
1766 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1767 dh.discOnus.Store(sn, false)
1768 }
1769 }()
1770
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301771 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1772
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301773 tpInstExists, error := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1774 if error != nil {
1775 return error
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301776 }
1777 if tpInstExists {
1778 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001779 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001780 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001781 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001782 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1783
1784 // if the ONU existed, handle the LOS Alarm
1785 if existing {
1786
1787 if inProcess.(bool) {
1788 // if we're currently processing the ONU on a different thread, do nothing
1789 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1790 return nil
1791 }
1792 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1793 // then continue processing it
1794 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1795
1796 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001797 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301798 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001799 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001800
1801 // check the ONU is already know to the OLT
1802 // NOTE the second time the ONU is discovered this should return a device
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301803 onuDevice, error := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001804 ParentId: dh.device.Id,
1805 SerialNumber: sn,
1806 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001807
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301808 if error != nil {
1809 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": error, "sn": sn})
1810 if e, ok := status.FromError(error); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811 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 -08001812 switch e.Code() {
1813 case codes.Internal:
1814 // this probably means NOT FOUND, so just create a new device
1815 onuDevice = nil
1816 case codes.DeadlineExceeded:
1817 // if the call times out, cleanup and exit
1818 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301819 error = olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, error)
1820 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001821 }
1822 }
1823 }
1824
1825 if onuDevice == nil {
1826 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001827 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001828 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001829 ponintfid := onuDiscInd.GetIntfId()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301830 onuID, error = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001831
Neha Sharma96b7bf22020-06-15 10:37:32 +00001832 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001833
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301834 if error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001835 // if we can't create an ID in resource manager,
1836 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001837 dh.discOnus.Delete(sn)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301838
1839 error = olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001840 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301841 "serial-number": sn}, error)
1842 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001843 }
1844
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301845 if onuDevice, error = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001846 ParentId: dh.device.Id,
1847 ParentPortNo: parentPortNo,
1848 ChannelId: channelID,
1849 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1850 SerialNumber: sn,
1851 OnuId: onuID,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301852 }); error != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001853 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001854 dh.resourceMgr[ponintfid].FreeonuID(ctx, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301855
1856 error = olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001857 "pon-intf-id": ponintfid,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301858 "serial-number": sn}, error)
1859 return error
Matteo Scandolo945e4012019-12-12 14:16:11 -08001860 }
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301861 if error := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); error != nil {
1862 logger.Error(ctx, "discovery-indication-failed", log.Fields{"err": error})
1863 error = olterrors.NewErrAdapter("discovery-indication-failed", log.Fields{
1864 "onu-id": onuID,
1865 "device-id": dh.device.Id,
1866 "serial-number": sn}, error)
1867 return error
Kent Hagermane6ff1012020-07-14 15:07:53 -04001868 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001869 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301870 log.Fields{"onuDevice": onuDevice,
1871 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001872 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301873 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001874 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001875
khenaidoo106c61a2021-08-11 18:05:46 -04001876 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1877 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301878 error = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
khenaidoo106c61a2021-08-11 18:05:46 -04001879 cancel()
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301880 if error != nil {
1881
1882 error = olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, error)
1883 return error
khenaidoo106c61a2021-08-11 18:05:46 -04001884 }
1885
Matteo Scandolo945e4012019-12-12 14:16:11 -08001886 // we can now use the existing ONU Id
1887 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001888 //Insert the ONU into cache to use in OnuIndication.
1889 //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 +00001890 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001891 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301892 "intfId": onuDiscInd.GetIntfId(),
1893 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001894 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001895
khenaidoo106c61a2021-08-11 18:05:46 -04001896 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301897 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001898 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301899 log.Fields{"onu": onuDev,
1900 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001901
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301902 if error = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001903 DeviceId: onuDevice.Id,
1904 ParentDeviceId: dh.device.Id,
1905 OperStatus: common.OperStatus_DISCOVERED,
1906 ConnStatus: common.ConnectStatus_REACHABLE,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301907 }); error != nil {
1908
1909 error = olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001910 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301911 "serial-number": sn}, error)
1912 return error
cuilin20187b2a8c32019-03-26 19:52:28 -07001913 }
khenaidoo106c61a2021-08-11 18:05:46 -04001914
Neha Sharma96b7bf22020-06-15 10:37:32 +00001915 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301916 if error = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); error != nil {
1917
1918 error = olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001919 "device-id": onuDevice.Id,
nikesh.krishnan3099ac12023-10-06 14:37:21 +05301920 "serial-number": sn}, error)
1921 return error
David K. Bainbridge794735f2020-02-11 21:01:37 -08001922 }
1923 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001924}
1925
Mahir Gunyelb0046752021-02-26 13:51:05 -08001926func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001927
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001928 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001929 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001930 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001931 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001932 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301933 log.Fields{"onuId": onuInd.OnuId,
1934 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301935 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001936 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001937 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301938
David K. Bainbridge794735f2020-02-11 21:01:37 -08001939 errFields := log.Fields{"device-id": dh.device.Id}
1940
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301941 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1942
Mahir Gunyele77977b2019-06-27 05:36:22 -07001943 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1944 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001945 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001946 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001947 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001948 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1949 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001950 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001951 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001952 errFields["onu-id"] = onuInd.OnuId
1953 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001954 }
khenaidoodc2116e2021-10-19 17:33:19 -04001955 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001956 ParentId: dh.device.Id,
1957 SerialNumber: serialNumber,
1958 OnuId: onuInd.OnuId,
1959 ParentPortNo: ponPort,
1960 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001961 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001962
David K. Bainbridge794735f2020-02-11 21:01:37 -08001963 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001964 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001965 }
1966
David K. Bainbridge794735f2020-02-11 21:01:37 -08001967 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001968 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001969 "previousIntfId": onuDevice.ParentPortNo,
1970 "currentIntfId": ponPort})
1971 }
1972
1973 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001974 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301975 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1976 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301977 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001978 }
1979 if !foundInCache {
1980 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1981
khenaidoo106c61a2021-08-11 18:05:46 -04001982 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 -08001983
1984 }
kesavand7cf3a052020-08-28 12:49:18 +05301985 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001986 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001987 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301988 }
1989 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001990 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001991 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001992 }
1993 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001994}
1995
Neha Sharma96b7bf22020-06-15 10:37:32 +00001996func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001997 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 -07001998 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1999 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
2000 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
2001 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07002002 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002003 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
2004 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002005 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00002006 onuInd.OperState = "down"
2007 }
2008 }
2009
David K. Bainbridge794735f2020-02-11 21:01:37 -08002010 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04002011 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00002012 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 -04002013
khenaidoodc2116e2021-10-19 17:33:19 -04002014 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002015 DeviceId: onuDevice.Id,
2016 OnuIndication: onuInd,
2017 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002018 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302019 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002020 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002021 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002022 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00002023 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002024 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002025 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00002026 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002027 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002028 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002029}
2030
cuilin20187b2a8c32019-03-26 19:52:28 -07002031func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
2032 if serialNum != nil {
2033 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07002034 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002035 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002036}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002037func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
2038 decodedStr, err := hex.DecodeString(serialNum[4:])
2039 if err != nil {
2040 return nil, err
2041 }
2042 return &oop.SerialNumber{
2043 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002044 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002045 }, nil
2046}
cuilin20187b2a8c32019-03-26 19:52:28 -07002047
2048func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08002049 if len(vendorSpecific) > 3 {
2050 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
2051 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
2052 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
2053 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
2054 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
2055 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
2056 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
2057 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
2058 return tmp
2059 }
2060 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07002061}
2062
Mahir Gunyela2e68702022-12-07 00:00:42 -08002063// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002064func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05302065 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07002066}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002067
Mahir Gunyela2e68702022-12-07 00:00:42 -08002068// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002069func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
2070 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05302071 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07002072 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05302073 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04002074
khenaidoodc2116e2021-10-19 17:33:19 -04002075 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002076 ParentId: dh.device.Id,
2077 OnuId: onuID,
2078 ParentPortNo: parentPort,
2079 })
2080
Girish Gowdru0c588b22019-04-23 23:24:56 -04002081 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002082 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002083 "intf-id": parentPort,
2084 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04002085 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002086 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 -08002087 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302088}
2089
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002090// SendPacketInToCore sends packet-in to core
2091// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
2092// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00002093func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002094 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002095 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002096 "port": logicalPort,
2097 "packet": hex.EncodeToString(packetPayload),
2098 "device-id": dh.device.Id,
2099 })
2100 }
khenaidoo106c61a2021-08-11 18:05:46 -04002101
khenaidoodc2116e2021-10-19 17:33:19 -04002102 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002103 DeviceId: dh.device.Id,
2104 Port: logicalPort,
2105 Packet: packetPayload,
2106 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302107 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002108 "source": "adapter",
2109 "destination": "core",
2110 "device-id": dh.device.Id,
2111 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00002112 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002113 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002114 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002115 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002116 "packet": hex.EncodeToString(packetPayload),
2117 "device-id": dh.device.Id,
2118 })
2119 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002120 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002121}
2122
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002123// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002124func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002126
2127 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
2128 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002129 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002130 }
2131
Kent Hagermane6ff1012020-07-14 15:07:53 -04002132 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00002133 metrics := dh.metrics.GetSubscriberMetrics()
2134 for _, m := range pmConfigs.Metrics {
2135 metrics[m.Name].Enabled = m.Enabled
2136
2137 }
2138 }
2139}
2140
khenaidoodc2116e2021-10-19 17:33:19 -04002141func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002142 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002143 var errorsList []error
2144
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002145 if dh.getDeviceDeletionInProgressFlag() {
2146 // The device itself is going to be reset as part of deletion. So nothing to be done.
2147 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2148 return nil
2149 }
2150
Girish Gowdru0c588b22019-04-23 23:24:56 -04002151 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002152 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00002153 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07002154
Neha Sharma96b7bf22020-06-15 10:37:32 +00002155 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302156 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002157 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302158 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002159 if flow_utils.HasGroup(flow) {
2160 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
2161 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002162 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2163 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2164 } else {
2165 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
2166 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002167 }
Girish Gowdracefae192020-03-19 18:14:10 -07002168 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01002169 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
2170 //The flow we want to remove is not there, there is no need to throw an error
2171 logger.Warnw(ctx, "flow-to-remove-not-found",
2172 log.Fields{
2173 "ponIf": intfID,
2174 "flowToRemove": flow,
2175 "error": err,
2176 })
2177 } else {
2178 errorsList = append(errorsList, err)
2179 }
Girish Gowdracefae192020-03-19 18:14:10 -07002180 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002181 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302182
2183 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00002184 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002185 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05302186 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00002187 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05302188 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002189 if flow_utils.HasGroup(flow) {
2190 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
2191 } else {
yasin saplid0566272021-12-21 09:10:30 +00002192 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002193 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
2194 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
2195 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
2196 } else {
yasin saplid0566272021-12-21 09:10:30 +00002197 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002198 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002199 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002200 if err != nil {
2201 errorsList = append(errorsList, err)
2202 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302203 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04002204 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002205
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002206 return errorsList
2207}
2208
2209func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
2210 var err error
2211 var errorsList []error
2212
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002213 if dh.getDeviceDeletionInProgressFlag() {
2214 // The device itself is going to be reset as part of deletion. So nothing to be done.
2215 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2216 return nil
2217 }
2218
Girish Gowdracefae192020-03-19 18:14:10 -07002219 // 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 +00002220 if groups != nil {
2221 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002222 // err = dh.groupMgr.AddGroup(ctx, group)
2223 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002224 if err != nil {
2225 errorsList = append(errorsList, err)
2226 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002227 }
2228 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002229 // err = dh.groupMgr.ModifyGroup(ctx, group)
2230 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002231 if err != nil {
2232 errorsList = append(errorsList, err)
2233 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002234 }
Esin Karamand519bbf2020-07-01 11:16:03 +00002235 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002236 // err = dh.groupMgr.DeleteGroup(ctx, group)
2237 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00002238 if err != nil {
2239 errorsList = append(errorsList, err)
2240 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002241 }
2242 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002243
2244 return errorsList
2245}
2246
Mahir Gunyela2e68702022-12-07 00:00:42 -08002247// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002248func (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 -07002249
2250 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002251
2252 if dh.getDeviceDeletionInProgressFlag() {
2253 // The device itself is going to be reset as part of deletion. So nothing to be done.
2254 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2255 return nil
2256 }
nikesh.krishnan0897d472023-09-05 18:35:08 +05302257 if dh.transitionMap.currentDeviceState != deviceStateUp {
2258 logger.Error(ctx, "device-is-not-up--not-handling-flows-or-groups", log.Fields{"device-id": device.Id, "current-device-state": dh.transitionMap.currentDeviceState})
2259 return fmt.Errorf("device-is-not-up--not-handling-flows-or-groups")
2260 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002261 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2262 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2263 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002264 if len(errorsList) > 0 {
2265 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2266 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002267 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002268 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302269}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002270
Mahir Gunyela2e68702022-12-07 00:00:42 -08002271// DisableDevice disables the given device
2272// It marks the following for the given device:
2273// Device-Handler Admin-State : down
2274// Device Port-State: UNKNOWN
2275// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002276func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002277 /* On device disable ,admin state update has to be done prior sending request to agent since
2278 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002279 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002280 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002281 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002282 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002283 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002284 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002285 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002286 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002287 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002288 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302289
2290 dh.discOnus = sync.Map{}
2291 dh.onus = sync.Map{}
2292
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002293 dh.lockDevice.RLock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302294 //stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002295 if dh.isCollectorActive {
2296 dh.stopCollector <- true
2297 }
2298 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302299
Neha Sharma96b7bf22020-06-15 10:37:32 +00002300 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002301 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05302302 //Update device Admin state
2303 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002304
kdarapu1afeceb2020-02-12 01:38:09 -05002305 // 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 -04002306 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002307 DeviceId: cloned.Id,
2308 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2309 OperStatus: voltha.OperStatus_UNKNOWN,
2310 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002311 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002312 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002313 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002314 return nil
2315}
2316
Neha Sharma96b7bf22020-06-15 10:37:32 +00002317func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002318 // Update onu state as unreachable in onu adapter
2319 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302320 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002321
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002322 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002323 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002324 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002325 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 -04002326 }
2327 if onuDevices != nil {
2328 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002329 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002330 DeviceId: onuDevice.Id,
2331 OnuIndication: &onuInd,
2332 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002333 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002334 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002335 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002336 }
2337
2338 }
2339 }
2340
2341}
2342
Mahir Gunyela2e68702022-12-07 00:00:42 -08002343// ReenableDevice re-enables the olt device after disable
2344// It marks the following for the given device:
2345// Device-Handler Admin-State : up
2346// Device Port-State: ACTIVE
2347// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002348func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302349 if dh.Client != nil {
2350 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2351 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
2352 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
2353 }
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302354 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302355 } else {
2356 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2357
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302358 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302359
Neha Sharma96b7bf22020-06-15 10:37:32 +00002360 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002361
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002362 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002363 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002364 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002365 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002366 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2367 } else {
2368 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2369 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2370 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002371 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002372 if retError == nil {
2373 //Update the device oper status as ACTIVE
2374 device.OperStatus = voltha.OperStatus_ACTIVE
2375 } else {
2376 //Update the device oper status as FAILED
2377 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002378 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002379 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002380
khenaidoodc2116e2021-10-19 17:33:19 -04002381 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002382 DeviceId: device.Id,
2383 OperStatus: device.OperStatus,
2384 ConnStatus: device.ConnectStatus,
2385 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302386 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002387 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002388 "connect-status": device.ConnectStatus,
2389 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002390 }
kesavand39e0aa32020-01-28 20:58:50 -05002391
Neha Sharma96b7bf22020-06-15 10:37:32 +00002392 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002393
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002394 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002395}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002396
npujarec5762e2020-01-01 14:08:48 +05302397func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002398 var uniID uint32
2399 var err error
Gustavo Silva41af9122022-10-11 11:05:13 -03002400 var errs []error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302401 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002402 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002403 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002404 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002405 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2406 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2407 } else {
2408 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2409 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002410 errs = append(errs, err)
Mahir Gunyela2e68702022-12-07 00:00:42 -08002411 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002412 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002413 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002414 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002415 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002416 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002417 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002418 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002419 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002420 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002421 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002422 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002423 errs = append(errs, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002424 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002425 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302426 }
yasin saplibddc2d72022-02-08 13:10:17 +00002427 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2428 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002429 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002430 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302431 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002432 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002433 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002434 logger.Debugw(ctx, "failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
Gustavo Silva41af9122022-10-11 11:05:13 -03002435 errs = append(errs, err)
A R Karthick1f85b802019-10-11 05:06:05 +00002436 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002437 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002438 if len(errs) > 0 {
2439 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-clear-uni-data, errors:%v",
2440 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2441 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002442 return nil
2443}
2444
Devmalya Paul495b94a2019-08-27 19:42:00 -04002445// 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 +05302446func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002447 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002448 /* Clear the KV store data associated with the all the UNI ports
2449 This clears up flow data and also resource map data for various
2450 other pon resources like alloc_id and gemport_id
2451 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002452
2453 dh.setDeviceDeletionInProgressFlag(true)
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002454
2455 dh.StopAllFlowRoutines(ctx)
Girish Gowdra950326e2021-11-05 12:43:24 -07002456
Gustavo Silva41af9122022-10-11 11:05:13 -03002457 err := dh.cleanupDeviceResources(ctx)
2458 if err != nil {
2459 logger.Errorw(ctx, "could-not-remove-device-from-KV-store", log.Fields{"device-id": dh.device.Id, "err": err})
2460 } else {
2461 logger.Debugw(ctx, "successfully-removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2462 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002463
Himani Chawla49a5d562020-11-25 11:53:44 +05302464 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002465 // Stop the Stats collector
2466 if dh.isCollectorActive {
2467 dh.stopCollector <- true
2468 }
2469 // stop the heartbeat check routine
2470 if dh.isHeartbeatCheckActive {
2471 dh.stopHeartbeatCheck <- true
2472 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302473 // Stop the read indication only if it the routine is active
2474 if dh.isReadIndicationRoutineActive {
2475 dh.stopIndications <- true
2476 }
2477 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002478 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002479 //Reset the state
2480 if dh.Client != nil {
2481 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002482 go func() {
2483 failureReason := fmt.Sprintf("Failed to reboot during device delete request with error: %s", err.Error())
2484 if err = dh.eventMgr.oltRebootFailedEvent(ctx, dh.device.Id, failureReason, time.Now().Unix()); err != nil {
2485 logger.Errorw(ctx, "on-olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
2486 }
2487 }()
2488 logger.Errorw(ctx, "olt-reboot-failed", log.Fields{"device-id": dh.device.Id, "err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002489 }
2490 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002491 // There is no need to update the core about operation status and connection status of the OLT.
2492 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2493 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2494 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002495
khenaidoo7eb2d672021-10-22 19:08:50 -04002496 // Stop the adapter grpc clients for that parent device
2497 dh.deleteAdapterClients(ctx)
Gustavo Silva41af9122022-10-11 11:05:13 -03002498 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002499}
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002500
2501// StopAllFlowRoutines stops all flow routines
2502func (dh *DeviceHandler) StopAllFlowRoutines(ctx context.Context) {
2503 var wg sync.WaitGroup
2504 wg.Add(1) // for the mcast routine below to finish
2505 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2506 for _, flMgr := range dh.flowMgr {
2507 if flMgr != nil {
2508 wg.Add(1) // for the flow handler routine below to finish
2509 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2510 }
2511 }
2512 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2513 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": dh.device.Id})
2514 } else {
2515 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": dh.device.Id})
2516 }
2517}
2518
Gustavo Silva41af9122022-10-11 11:05:13 -03002519func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
2520 var errs []error
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002521 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302522 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002523 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
yasin sapli9e4c5092022-02-01 13:52:33 +00002524 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002525 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002526 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Gustavo Silva41af9122022-10-11 11:05:13 -03002527 if err := dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
2528 errs = append(errs, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302529 }
2530 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002531 if err := dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2532 errs = append(errs, err)
2533 }
2534 if err := dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx); err != nil {
2535 errs = append(errs, err)
2536 }
2537 if err := dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx); err != nil {
2538 errs = append(errs, err)
2539 }
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002540 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
Gustavo Silva41af9122022-10-11 11:05:13 -03002541 errs = append(errs, err)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002542 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002543 }
Gustavo Silva41af9122022-10-11 11:05:13 -03002544 }
2545 // Clean up NNI manager's data
2546 if err := dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx); err != nil {
2547 errs = append(errs, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002548 }
A R Karthick1f85b802019-10-11 05:06:05 +00002549
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002550 dh.CloseKVClient(ctx)
2551
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002552 // Take one final sweep at cleaning up KV store for the OLT device
2553 // Clean everything at <base-path-prefix>/openolt/<device-id>
Gustavo Silva41af9122022-10-11 11:05:13 -03002554 if err := dh.kvStore.DeleteWithPrefix(ctx, ""); err != nil {
2555 errs = append(errs, err)
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002556 }
2557
Devmalya Paul495b94a2019-08-27 19:42:00 -04002558 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302559 dh.onus.Range(func(key interface{}, value interface{}) bool {
2560 dh.onus.Delete(key)
2561 return true
2562 })
2563
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002564 /*Delete discovered ONU map for the device*/
2565 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2566 dh.discOnus.Delete(key)
2567 return true
2568 })
Gustavo Silva41af9122022-10-11 11:05:13 -03002569 if len(errs) > 0 {
2570 return olterrors.NewErrAdapter(fmt.Errorf("one-or-more-error-during-device-delete, errors:%v",
2571 errs).Error(), log.Fields{"device-id": dh.device.Id}, nil)
2572 }
2573 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04002574}
2575
Mahir Gunyela2e68702022-12-07 00:00:42 -08002576// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002577func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
nikesh.krishnane363ace2023-02-28 03:12:38 +05302578 if dh.Client != nil {
2579 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
2580 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
2581 }
2582 } else {
2583 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, errors.New("nil device client"))
2584
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002585 }
nikesh.krishnane363ace2023-02-28 03:12:38 +05302586
Neha Sharma96b7bf22020-06-15 10:37:32 +00002587 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002588 return nil
2589}
2590
David K. Bainbridge794735f2020-02-11 21:01:37 -08002591func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002592 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002593 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002594 "packet-indication": *packetIn,
2595 "device-id": dh.device.Id,
2596 "packet": hex.EncodeToString(packetIn.Pkt),
2597 })
2598 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002599 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2600 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2601 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002602 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002603 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002604 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002605 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002606 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002607 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002608 "logical-port-num": logicalPortNum,
2609 "device-id": dh.device.Id,
2610 "packet": hex.EncodeToString(packetIn.Pkt),
2611 })
2612 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002613
khenaidoodc2116e2021-10-19 17:33:19 -04002614 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002615 DeviceId: dh.device.Id,
2616 Port: logicalPortNum,
2617 Packet: packetIn.Pkt,
2618 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302619 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002620 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302621 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002622 "device-id": dh.device.Id,
2623 "packet": hex.EncodeToString(packetIn.Pkt),
2624 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002625 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002626
Matteo Scandolo92186242020-06-12 10:54:18 -07002627 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002628 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002629 "packet": hex.EncodeToString(packetIn.Pkt),
2630 "device-id": dh.device.Id,
2631 })
2632 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002633 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002634}
2635
Mahir Gunyela2e68702022-12-07 00:00:42 -08002636// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2637func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2638 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2639 if err != nil {
2640 return olterrors.NewErrInvalidValue(log.Fields{
2641 "egress-nni-port": egressPortNo,
2642 "device-id": dh.device.Id,
2643 }, err)
2644 }
2645 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2646
2647 if logger.V(log.DebugLevel) {
2648 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2649 "uplink-pkt": uplinkPkt,
2650 "packet": hex.EncodeToString(packet.Data),
2651 "device-id": dh.device.Id,
2652 })
2653 }
2654
2655 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2656 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2657 "packet": hex.EncodeToString(packet.Data),
2658 "device-id": dh.device.Id,
2659 }, err)
2660 }
2661 return nil
2662}
2663
2664// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2665func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2666 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2667 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2668 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2669 // Do not packet-out lldp packets on uni port.
2670 // ONOS has no clue about uni/nni ports, it just packets out on all
2671 // available ports on the Logical Switch. It should not be interested
2672 // in the UNI links.
2673 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2674 "device-id": dh.device.Id,
2675 })
2676 return nil
2677 }
2678 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2679 if innerEthType == 0x8100 {
2680 // q-in-q 802.1ad or 802.1q double tagged packet.
2681 // slice out the outer tag.
2682 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2683 if logger.V(log.DebugLevel) {
2684 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2685 "packet-data": hex.EncodeToString(packet.Data),
2686 "device-id": dh.device.Id,
2687 })
2688 }
2689 }
2690 }
2691 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2692 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2693 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2694 var gemPortID uint32
2695 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2696 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2697 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2698 }
2699 if err != nil {
2700 // In this case the openolt agent will receive the gemPortID as 0.
2701 // The agent tries to retrieve the gemPortID in this case.
2702 // This may not always succeed at the agent and packetOut may fail.
2703 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2704 "intf-id": intfID,
2705 "onu-id": onuID,
2706 "uni-id": uniID,
2707 "packet": hex.EncodeToString(packet.Data),
2708 "device-id": dh.device.Id,
2709 "error": err,
2710 })
2711 }
2712
2713 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2714 if logger.V(log.DebugLevel) {
2715 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2716 "egress-port-no": egressPortNo,
2717 "intf-id": intfID,
2718 "onu-id": onuID,
2719 "uni-id": uniID,
2720 "gem-port-id": gemPortID,
2721 "packet": hex.EncodeToString(packet.Data),
2722 "device-id": dh.device.Id,
2723 })
2724 }
2725
2726 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2727 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2728 "source": "adapter",
2729 "destination": "onu",
2730 "egress-port-number": egressPortNo,
2731 "intf-id": intfID,
2732 "oni-id": onuID,
2733 "uni-id": uniID,
2734 "gem-port-id": gemPortID,
2735 "packet": hex.EncodeToString(packet.Data),
2736 "device-id": dh.device.Id,
2737 }, err)
2738 }
2739 return nil
2740}
2741
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002742// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002743func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002744 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002745 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002746 "device-id": dh.device.Id,
2747 "egress-port-no": egressPortNo,
2748 "pkt-length": len(packet.Data),
2749 "packet": hex.EncodeToString(packet.Data),
2750 })
2751 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002752
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002753 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002754 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002755 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002756 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002757 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002758 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002759 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002760 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302761 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002762 "egressPortType": egressPortType,
2763 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302764 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002765 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002766 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002767 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002768}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002769
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002770func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2771 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002772}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302773
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002774func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002775
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002776 defer func() {
2777 dh.lockDevice.Lock()
2778 dh.isHeartbeatCheckActive = false
2779 dh.lockDevice.Unlock()
2780 }()
2781
2782 dh.lockDevice.Lock()
2783 dh.isHeartbeatCheckActive = true
2784 dh.lockDevice.Unlock()
2785
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302786 // start the heartbeat check towards the OLT.
2787 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302788 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302789
2790 for {
2791 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2792 select {
2793 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002794 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002795 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002796 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302797 if timerCheck == nil {
2798 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002799 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302800 }
2801 } else {
2802 if timerCheck != nil {
2803 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002804 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302805 }
2806 timerCheck = nil
2807 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302808 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2809 if dh.heartbeatSignature == 0 {
2810 // First time the signature will be 0, update the signture to DB when not found.
2811 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2812 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2813 }
2814 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2815
2816 dh.lockDevice.RLock()
2817 // Stop the read indication only if it the routine is active
2818 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2819 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2820 // on next execution of the readIndication routine.
2821 if !dh.isReadIndicationRoutineActive {
2822 // Start reading indications
2823 go func() {
2824 if err = dh.readIndications(ctx); err != nil {
2825 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2826 }
2827 }()
2828 }
2829 dh.lockDevice.RUnlock()
2830
2831 } else {
2832 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2833 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2834 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2835 go dh.updateStateRebooted(ctx)
2836 }
2837
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302838 }
2839 cancel()
2840 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002841 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302842 return
2843 }
2844 }
2845}
2846
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002847func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002848 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002849 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002850 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2851 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2852 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2853 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2854 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002855 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002856 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2857 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002858 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302859
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302860 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002861 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002862 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002863 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002864 DeviceId: dh.device.Id,
2865 OperStatus: voltha.OperStatus_UNKNOWN,
2866 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2867 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002868 _ = 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 -04002869 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302870 /*
2871 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2872 DeviceId: dh.device.Id,
2873 PortTypeFilter: 0,
2874 OperStatus: voltha.OperStatus_UNKNOWN,
2875 }); err != nil {
2876 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2877 }
2878 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002879
2880 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002881 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002882 cloned := proto.Clone(device).(*voltha.Device)
2883 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2884 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2885 dh.device = cloned // update local copy of the device
2886 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002887
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002888 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002889 // Stop the Stats collector
2890 if dh.isCollectorActive {
2891 dh.stopCollector <- true
2892 }
2893 // stop the heartbeat check routine
2894 if dh.isHeartbeatCheckActive {
2895 dh.stopHeartbeatCheck <- true
2896 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002897 // Stop the read indication only if it the routine is active
2898 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2899 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2900 // on next execution of the readIndication routine.
2901 if dh.isReadIndicationRoutineActive {
2902 dh.stopIndications <- true
2903 }
2904 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002905 dh.transitionMap.Handle(ctx, DeviceInit)
2906
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302907 }
2908}
kesavand39e0aa32020-01-28 20:58:50 -05002909
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302910func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2911 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2912 if err != nil || device == nil {
2913 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2914 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2915 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2916 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2917 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2918 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2919 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2920 return
2921 }
Mahir Gunyel701df862023-09-07 16:16:04 -07002922 //Starting the cleanup process
2923 dh.setDeviceDeletionInProgressFlag(true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302924
2925 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2926 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2927 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2928 DeviceId: dh.device.Id,
2929 OperStatus: voltha.OperStatus_REBOOTED,
2930 ConnStatus: voltha.ConnectStatus_REACHABLE,
2931 }); err != nil {
2932 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2933 }
2934
2935 dh.lockDevice.RLock()
2936 // Stop the read indication only if it the routine is active
2937 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2938 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2939 // on next execution of the readIndication routine.
2940 if dh.isReadIndicationRoutineActive {
2941 dh.stopIndications <- true
2942 }
2943 dh.lockDevice.RUnlock()
2944
2945 //raise olt communication failure event
2946 raisedTs := time.Now().Unix()
2947 cloned := proto.Clone(device).(*voltha.Device)
2948 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2949 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2950 dh.device = cloned // update local copy of the device
2951 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2952
Gustavo Silva41af9122022-10-11 11:05:13 -03002953 if err := dh.cleanupDeviceResources(ctx); err != nil {
2954 logger.Errorw(ctx, "failure-in-cleanup-device-resources", log.Fields{"device-id": dh.device.Id, "err": err})
2955 } else {
2956 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
2957 }
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002958
2959 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302960 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002961 if dh.isCollectorActive {
2962 dh.stopCollector <- true
2963 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302964 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002965 if dh.isHeartbeatCheckActive {
2966 dh.stopHeartbeatCheck <- true
2967 }
2968 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302969
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002970 dh.StopAllFlowRoutines(ctx)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302971
2972 //reset adapter reconcile flag
2973 dh.adapterPreviouslyConnected = false
2974 for {
2975
2976 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2977 if err != nil || childDevices == nil {
2978 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2979 continue
2980 }
2981 if len(childDevices.Items) == 0 {
2982 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
2983 break
2984 } else {
2985 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
2986 time.Sleep(5 * time.Second)
2987 }
2988
2989 }
Mahir Gunyel701df862023-09-07 16:16:04 -07002990 //Cleanup completed , reset the flag
2991 dh.setDeviceDeletionInProgressFlag(false)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302992 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
2993 dh.transitionMap.Handle(ctx, DeviceInit)
2994
2995}
2996
kesavand39e0aa32020-01-28 20:58:50 -05002997// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002998func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2999 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
3000 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05003001}
3002
3003// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00003004func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
3005 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
3006 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05003007}
3008
Mahir Gunyela2e68702022-12-07 00:00:42 -08003009// 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 +00003010func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
3011 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05003012 if port.GetType() == voltha.Port_ETHERNET_NNI {
3013 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00003014 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05303015 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05303016 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003017 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00003018 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05003019 }
3020 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003021 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05003022 ponIntf := &oop.Interface{IntfId: ponID}
3023 var operStatus voltha.OperStatus_Types
3024 if enablePort {
3025 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05303026 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003027
3028 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303029 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003030 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003031 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003032 }
3033 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003034 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003035 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003036 } else {
3037 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05303038 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05003039 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303040 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003041 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003042 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003043 }
3044 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05003045 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003046 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05003047 }
khenaidoodc2116e2021-10-19 17:33:19 -04003048 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04003049 DeviceId: dh.device.Id,
3050 PortType: voltha.Port_PON_OLT,
3051 PortNo: port.PortNo,
3052 OperStatus: operStatus,
3053 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303054 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303055 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003056 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003057 }
3058 return nil
3059}
3060
Mahir Gunyela2e68702022-12-07 00:00:42 -08003061// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003062func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05003063 // Disable the port and update the oper_port_status to core
3064 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003065 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003066 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303068 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303069 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00003070 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05003071 }
3072 }
3073 }
3074 return nil
3075}
3076
Mahir Gunyela2e68702022-12-07 00:00:42 -08003077// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04003078func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
3079 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
3080 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05003081 if port.Type == voltha.Port_ETHERNET_NNI {
3082 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003083 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05003084 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003085 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05003086 }
3087 }
3088 if port.Type == voltha.Port_PON_OLT {
3089 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003090 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05003091 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003092 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05003093 }
3094 }
3095 }
3096}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003097
3098// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08003099func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00003100 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07003101 if dh.getDeviceDeletionInProgressFlag() {
3102 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
3103 // will reboot, so everything will be reset on the pOLT too.
3104 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
3105 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
3106 return nil
3107 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003108 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003109 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08003110
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003111 var sn *oop.SerialNumber
3112 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08003113 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303114 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003115 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303116 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08003117 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003118 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003119
Girish Gowdra89ae6d82020-05-28 23:40:53 -07003120 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003121 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00003122 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003123 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
3124 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
3125 "device-id": dh.device.Id,
3126 "intf-id": intfID,
3127 "onuID": onuID,
3128 "err": err})
3129 } else {
3130 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00003131 // Delete flows from device before schedulers and queue
3132 // Clear flowids for gem cache.
3133 removedFlows := []uint64{}
3134 for _, gem := range onuGem.GemPorts {
3135 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
3136 for _, flowID := range flowIDs {
3137 //multiple gem port can have the same flow id
3138 //it is better to send only one flowRemove request to the agent
3139 var alreadyRemoved bool
3140 for _, removedFlowID := range removedFlows {
3141 if removedFlowID == flowID {
3142 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
3143 alreadyRemoved = true
3144 break
3145 }
3146 }
3147 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08003148 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00003149 removedFlows = appendUnique64bit(removedFlows, flowID)
3150 }
3151 }
3152 }
3153 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
3154 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003155 if err := dh.clearUNIData(ctx, onuGem); err != nil {
3156 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
3157 "device-id": dh.device.Id,
3158 "onu-device": onu,
3159 "err": err})
3160 }
yasin saplibddc2d72022-02-08 13:10:17 +00003161 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003162 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
3163 "intf-id": intfID,
3164 "onu-device": onu,
3165 "onu-gem": onuGem,
3166 "err": err})
3167 //Not returning error on cleanup.
3168 }
3169 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05303170
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003171 }
yasin saplibddc2d72022-02-08 13:10:17 +00003172 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003173 dh.onus.Delete(onuKey)
3174 dh.discOnus.Delete(onuSn)
3175
3176 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00003177 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303178 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05303179 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003180 "onu-id": onuID}, err).Log()
3181 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003182
Chaitrashree G S1a55b882020-02-04 17:35:35 -05003183 return nil
3184}
Mahir Gunyela2e68702022-12-07 00:00:42 -08003185func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
3186 flow := &oop.Flow{FlowId: flowID}
3187 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
3188 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
3189 "device-id": dh.device.Id})
3190 } else {
3191 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
3192 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
3193 "device-id": dh.device.Id,
3194 "err": err})
3195 }
3196 }
3197}
Girish Gowdracefae192020-03-19 18:14:10 -07003198
3199func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003200 for _, field := range flow_utils.GetOfbFields(flow) {
3201 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07003202 return field.GetPort()
3203 }
3204 }
3205 return InvalidPort
3206}
3207
3208func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003209 for _, action := range flow_utils.GetActions(flow) {
3210 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07003211 if out := action.GetOutput(); out != nil {
3212 return out.GetPort()
3213 }
3214 }
3215 }
3216 return InvalidPort
3217}
3218
Girish Gowdracefae192020-03-19 18:14:10 -07003219func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
3220 inPort := getInPortFromFlow(flow)
3221 outPort := getOutPortFromFlow(flow)
3222
3223 if inPort == InvalidPort || outPort == InvalidPort {
3224 return inPort, outPort
3225 }
3226
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003227 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07003228 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003229 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003230 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003231 return uniPort, outPort
3232 }
3233 }
3234 } else {
3235 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003236 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003237 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003238 return inPort, uniPort
3239 }
3240 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003241 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003242 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07003243 return uniPort, outPort
3244 }
3245 }
3246 }
3247
3248 return InvalidPort, InvalidPort
3249}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04003250
3251func extractOmciTransactionID(omciPkt []byte) uint16 {
3252 if len(omciPkt) > 3 {
3253 d := omciPkt[0:2]
3254 transid := binary.BigEndian.Uint16(d)
3255 return transid
3256 }
3257 return 0
3258}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07003259
3260// StoreOnuDevice stores the onu parameters to the local cache.
3261func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
3262 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
3263 dh.onus.Store(onuKey, onuDevice)
3264}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003265
khenaidoodc2116e2021-10-19 17:33:19 -04003266func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003267 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02003268 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003269 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04003270 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003271 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00003272 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003273 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003274 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
3275 return nil, err
3276 }
3277 ID = device.ProxyAddress.GetOnuId()
3278 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
3279 valueparam.Onu = &Onu
3280 valueparam.Value = value
3281
3282 // This API is unsupported until agent patch is added
3283 resp.Unsupported = uint32(value)
3284 _ = ctx
3285
3286 // Uncomment this code once agent changes are complete and tests
3287 /*
3288 resp, err = dh.Client.GetValue(ctx, valueparam)
3289 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003290 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003291 return nil, err
3292 }
3293 */
3294
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003295 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 -08003296 return resp, nil
3297}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003298
yasin saplid0566272021-12-21 09:10:30 +00003299func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
3300 // Default to NNI
3301 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003302 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003303 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003304 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003305 }
3306 return intfID
3307}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003308
Mahir Gunyelb0046752021-02-26 13:51:05 -08003309func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
3310 dh.perPonOnuIndicationChannelLock.Lock()
3311 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3312 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003313 return ch.indicationChannel
3314 }
3315 channels := onuIndicationChannels{
3316 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08003317 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003318 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003319 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003320 stopChannel: make(chan struct{}),
3321 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003322 dh.perPonOnuIndicationChannel[intfID] = channels
3323 dh.perPonOnuIndicationChannelLock.Unlock()
3324 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003325 return channels.indicationChannel
3326
3327}
3328
Mahir Gunyelb0046752021-02-26 13:51:05 -08003329func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3330 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3331 dh.perPonOnuIndicationChannelLock.Lock()
3332 defer dh.perPonOnuIndicationChannelLock.Unlock()
3333 for _, v := range dh.perPonOnuIndicationChannel {
3334 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003335 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003336 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003337}
3338
Mahir Gunyelb0046752021-02-26 13:51:05 -08003339func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3340 ind := onuIndicationMsg{
3341 ctx: ctx,
3342 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003343 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003344 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003345 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003346 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003347}
3348
Mahir Gunyelb0046752021-02-26 13:51:05 -08003349func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003350 for {
3351 select {
3352 // process one indication per onu, before proceeding to the next one
3353 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003354 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003355 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003356 "ind": indication})
3357 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003358 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003359 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003360 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3361 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003362 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003363 }
3364 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003365 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003366 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3367 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003368 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003369 }
3370 }
3371 case <-onuChannels.stopChannel:
3372 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3373 close(onuChannels.indicationChannel)
3374 return
3375 }
3376 }
3377}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003378
3379// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3380// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003381func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003382 if dh.getDeviceDeletionInProgressFlag() {
3383 // The device itself is going to be reset as part of deletion. So nothing to be done.
3384 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3385 return nil
3386 }
3387
Girish Gowdra491a9c62021-01-06 16:43:07 -08003388 // Step1 : Fill McastFlowOrGroupControlBlock
3389 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3390 // Step3 : Wait on response channel for response
3391 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003392 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003393 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3394 errChan := make(chan error)
3395 var groupID uint32
3396 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3397 ctx: ctx,
3398 flowOrGroupAction: action,
3399 flow: flow,
3400 group: group,
3401 errChan: &errChan,
3402 }
3403 if flow != nil {
3404 groupID = flow_utils.GetGroup(flow)
3405 } else if group != nil {
3406 groupID = group.Desc.GroupId
3407 } else {
3408 return errors.New("flow-and-group-both-nil")
3409 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003410 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3411 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3412 // Derive the appropriate go routine to handle the request by a simple module operation.
3413 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3414 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3415 // Wait for handler to return error value
3416 err := <-errChan
3417 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3418 return err
3419 }
3420 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3421 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003422}
3423
3424// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003425func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003426 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003427 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003428 // block on the channel to receive an incoming mcast flow/group
3429 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003430 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3431 if mcastFlowOrGroupCb.flow != nil {
3432 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3433 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3434 log.Fields{"device-id": dh.device.Id,
3435 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003436 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3437 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3438 for _, flMgr := range dh.flowMgr {
3439 if flMgr != nil {
3440 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3441 break
3442 }
3443 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003444 // Pass the return value over the return channel
3445 *mcastFlowOrGroupCb.errChan <- err
3446 } else { // flow remove
3447 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3448 log.Fields{"device-id": dh.device.Id,
3449 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003450 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3451 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3452 for _, flMgr := range dh.flowMgr {
3453 if flMgr != nil {
3454 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3455 break
3456 }
3457 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003458 // Pass the return value over the return channel
3459 *mcastFlowOrGroupCb.errChan <- err
3460 }
3461 } else { // mcast group
3462 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3463 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3464 log.Fields{"device-id": dh.device.Id,
3465 "groupToAdd": mcastFlowOrGroupCb.group})
3466 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3467 // Pass the return value over the return channel
3468 *mcastFlowOrGroupCb.errChan <- err
3469 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3470 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3471 log.Fields{"device-id": dh.device.Id,
3472 "groupToModify": mcastFlowOrGroupCb.group})
3473 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3474 // Pass the return value over the return channel
3475 *mcastFlowOrGroupCb.errChan <- err
3476 } else { // group remove
3477 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3478 log.Fields{"device-id": dh.device.Id,
3479 "groupToRemove": mcastFlowOrGroupCb.group})
3480 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3481 // Pass the return value over the return channel
3482 *mcastFlowOrGroupCb.errChan <- err
3483 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003484 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003485 case <-stopHandler:
3486 dh.mcastHandlerRoutineActive[routineIndex] = false
3487 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003488 }
3489 }
3490}
kesavand62126212021-01-12 04:56:06 -05003491
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003492// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003493func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003494 for i, v := range dh.stopMcastHandlerRoutine {
3495 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003496 select {
3497 case v <- true:
3498 case <-time.After(time.Second * 5):
3499 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3500 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003501 }
3502 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00003503
3504 if dh.incomingMcastFlowOrGroup != nil {
3505 for k := range dh.incomingMcastFlowOrGroup {
3506 if dh.incomingMcastFlowOrGroup[k] != nil {
3507 dh.incomingMcastFlowOrGroup[k] = nil
3508 }
3509 }
3510 dh.incomingMcastFlowOrGroup = nil
3511 }
3512
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003513 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003514 logger.Debug(ctx, "stopped all mcast handler routines")
3515}
3516
kesavand62126212021-01-12 04:56:06 -05003517func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3518
3519 singleValResp := extension.SingleGetValueResponse{
3520 Response: &extension.GetValueResponse{
3521 Response: &extension.GetValueResponse_PortCoutners{
3522 PortCoutners: &extension.GetOltPortCountersResponse{},
3523 },
3524 },
3525 }
3526
3527 errResp := func(status extension.GetValueResponse_Status,
3528 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3529 return &extension.SingleGetValueResponse{
3530 Response: &extension.GetValueResponse{
3531 Status: status,
3532 ErrReason: reason,
3533 },
3534 }
3535 }
3536
3537 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3538 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3539 //send error response
3540 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3541 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3542 }
3543 statIndChn := make(chan bool, 1)
3544 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3545 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3546 //request openOlt agent to send the the port statistics indication
3547
3548 go func() {
3549 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3550 if err != nil {
3551 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3552 }
3553 }()
3554 select {
3555 case <-statIndChn:
3556 //indication received for ports stats
3557 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3558 case <-time.After(oltPortInfoTimeout * time.Second):
3559 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3560 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3561 case <-ctx.Done():
3562 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3563 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3564 }
3565 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3566 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003567 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003568 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3569 cmnni := dh.portStats.collectNNIMetrics(intfID)
3570 if cmnni == nil {
3571 //TODO define the error reason
3572 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3573 }
3574 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3575 return &singleValResp
3576
3577 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3578 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003579 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003580 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3581 cmpon := dh.portStats.collectPONMetrics(intfID)
3582 if cmpon == nil {
3583 //TODO define the error reason
3584 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3585 }
3586 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3587 return &singleValResp
3588 }
3589 }
3590 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3591}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303592
3593func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3594
3595 singleValResp := extension.SingleGetValueResponse{
3596 Response: &extension.GetValueResponse{
3597 Response: &extension.GetValueResponse_OnuPonCounters{
3598 OnuPonCounters: &extension.GetOnuCountersResponse{},
3599 },
3600 },
3601 }
3602
3603 errResp := func(status extension.GetValueResponse_Status,
3604 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3605 return &extension.SingleGetValueResponse{
3606 Response: &extension.GetValueResponse{
3607 Status: status,
3608 ErrReason: reason,
3609 },
3610 }
3611 }
3612 intfID := onuPonInfo.IntfId
3613 onuID := onuPonInfo.OnuId
3614 onuKey := dh.formOnuKey(intfID, onuID)
3615
3616 if _, ok := dh.onus.Load(onuKey); !ok {
3617 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3618 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3619 }
3620 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3621 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3622 if cmnni == nil {
3623 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3624 }
3625 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3626 return &singleValResp
3627
3628}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003629
nikesh.krishnanc8473432023-06-14 12:14:54 +05303630func (dh *DeviceHandler) getOnuInfo(ctx context.Context, intfID uint32, onuID *uint32) (*oop.OnuInfo, error) {
3631
3632 Onu := oop.Onu{IntfId: intfID, OnuId: *onuID}
3633 OnuInfo, err := dh.Client.GetOnuInfo(ctx, &Onu)
3634 if err != nil {
3635 return nil, err
3636 }
3637 return OnuInfo, nil
3638
3639}
3640
3641func (dh *DeviceHandler) getIntfInfo(ctx context.Context, intfID uint32) (*oop.PonIntfInfo, error) {
3642
3643 Intf := oop.Interface{IntfId: intfID}
3644 IntfInfo, err := dh.Client.GetPonInterfaceInfo(ctx, &Intf)
3645 if err != nil {
3646 return nil, err
3647 }
3648 return IntfInfo, nil
3649
3650}
3651
Gamze Abaka85e9a142021-05-26 13:41:39 +00003652func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3653
3654 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3655 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3656 if err != nil {
3657 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3658 return generateSingleGetValueErrorResponse(err)
3659 }
3660 return &extension.SingleGetValueResponse{
3661 Response: &extension.GetValueResponse{
3662 Status: extension.GetValueResponse_OK,
3663 Response: &extension.GetValueResponse_RxPower{
3664 RxPower: &extension.GetRxPowerResponse{
3665 IntfId: rxPowerRequest.IntfId,
3666 OnuId: rxPowerRequest.OnuId,
3667 Status: rxPower.Status,
3668 FailReason: rxPower.FailReason.String(),
3669 RxPower: rxPower.RxPowerMeanDbm,
3670 },
3671 },
3672 },
3673 }
3674}
3675
praneeth nalmas55616d62023-02-06 09:19:18 +05303676func (dh *DeviceHandler) getPONRxPower(ctx context.Context, OltRxPowerRequest *extension.GetOltRxPowerRequest) *extension.SingleGetValueResponse {
3677
3678 errResp := func(status extension.GetValueResponse_Status,
3679 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3680 return &extension.SingleGetValueResponse{
3681 Response: &extension.GetValueResponse{
3682 Status: status,
3683 ErrReason: reason,
3684 },
3685 }
3686 }
3687
3688 resp := extension.SingleGetValueResponse{
3689 Response: &extension.GetValueResponse{
3690 Status: extension.GetValueResponse_OK,
3691 Response: &extension.GetValueResponse_OltRxPower{
3692 OltRxPower: &extension.GetOltRxPowerResponse{},
3693 },
3694 },
3695 }
3696
3697 logger.Debugw(ctx, "getPONRxPower", log.Fields{"portLabel": OltRxPowerRequest.PortLabel, "OnuSerialNumber": OltRxPowerRequest.OnuSn, "device-id": dh.device.Id})
3698 portLabel := OltRxPowerRequest.PortLabel
3699 serialNumber := OltRxPowerRequest.OnuSn
3700
3701 portInfo := strings.Split(portLabel, "-")
3702 portNumber, err := strconv.ParseUint(portInfo[1], 10, 32)
3703
3704 if err != nil {
3705 logger.Errorw(ctx, "getPONRxPower invalid portNumber ", log.Fields{"oltPortNumber": portInfo[1]})
3706 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_REQ_TYPE)
3707 }
3708
3709 if portInfo[0] != "pon" {
3710 logger.Errorw(ctx, "getPONRxPower invalid portType", log.Fields{"oltPortType": portInfo[0]})
3711 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3712 }
praneeth nalmas55616d62023-02-06 09:19:18 +05303713
3714 if serialNumber != "" {
3715
3716 onuDev := dh.getChildDevice(ctx, serialNumber, (uint32)(portNumber))
3717 if onuDev != nil {
3718
3719 Onu := oop.Onu{IntfId: uint32(portNumber), OnuId: onuDev.onuID}
3720 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3721 if err != nil {
3722
3723 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3724 return generateSingleGetValueErrorResponse(err)
3725
3726 }
3727
3728 rxPowerValue := extension.RxPower{}
3729 rxPowerValue.OnuSn = onuDev.serialNumber
3730 rxPowerValue.Status = rxPower.GetStatus()
3731 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3732 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3733
3734 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3735
3736 } else {
3737
3738 logger.Errorw(ctx, "getPONRxPower invalid Device", log.Fields{"portLabel": portLabel, "serialNumber": serialNumber})
3739 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3740 }
3741
3742 } else {
3743
3744 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303745 if onuInCache.(*OnuDevice).intfID == (uint32)(portNumber) {
praneeth nalmas55616d62023-02-06 09:19:18 +05303746
praneeth kumar nalmasb234f232023-11-29 12:50:46 +05303747 Onu := oop.Onu{IntfId: (uint32)(portNumber), OnuId: onuInCache.(*OnuDevice).onuID}
praneeth nalmas55616d62023-02-06 09:19:18 +05303748 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3749 if err != nil {
3750 logger.Errorw(ctx, "error-while-getting-rx-power, however considering to proceed further with other ONUs on PON", log.Fields{"Onu": Onu, "err": err})
3751 } else {
3752
3753 rxPowerValue := extension.RxPower{}
3754 rxPowerValue.OnuSn = onuInCache.(*OnuDevice).serialNumber
3755 rxPowerValue.Status = rxPower.GetStatus()
3756 rxPowerValue.RxPower = rxPower.GetRxPowerMeanDbm()
3757 rxPowerValue.FailReason = rxPower.GetFailReason().String()
3758
3759 resp.Response.GetOltRxPower().RxPower = append(resp.Response.GetOltRxPower().RxPower, &rxPowerValue)
3760 }
3761
3762 }
3763 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3764 return true
3765 })
3766 }
3767 logger.Infow(ctx, "getPONRxPower response ", log.Fields{"Response": resp})
3768 return &resp
3769}
3770
Gamze Abaka85e9a142021-05-26 13:41:39 +00003771func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3772 errResp := func(status extension.GetValueResponse_Status,
3773 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3774 return &extension.SingleGetValueResponse{
3775 Response: &extension.GetValueResponse{
3776 Status: status,
3777 ErrReason: reason,
3778 },
3779 }
3780 }
3781
3782 if err != nil {
3783 if e, ok := status.FromError(err); ok {
3784 switch e.Code() {
3785 case codes.Internal:
3786 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3787 case codes.DeadlineExceeded:
3788 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3789 case codes.Unimplemented:
3790 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3791 case codes.NotFound:
3792 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3793 }
3794 }
3795 }
3796
3797 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3798}
khenaidoo106c61a2021-08-11 18:05:46 -04003799
3800/*
3801Helper functions to communicate with Core
3802*/
3803
3804func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3805 cClient, err := dh.coreClient.GetCoreServiceClient()
3806 if err != nil || cClient == nil {
3807 return nil, err
3808 }
3809 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3810 defer cancel()
3811 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3812}
3813
khenaidoodc2116e2021-10-19 17:33:19 -04003814func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003815 cClient, err := dh.coreClient.GetCoreServiceClient()
3816 if err != nil || cClient == nil {
3817 return nil, err
3818 }
3819 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3820 defer cancel()
3821 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3822}
3823
khenaidoodc2116e2021-10-19 17:33:19 -04003824func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003825 cClient, err := dh.coreClient.GetCoreServiceClient()
3826 if err != nil || cClient == nil {
3827 return err
3828 }
3829 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3830 defer cancel()
3831 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3832 return err
3833}
3834
3835func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3836 cClient, err := dh.coreClient.GetCoreServiceClient()
3837 if err != nil || cClient == nil {
3838 return nil, err
3839 }
3840 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3841 defer cancel()
3842 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3843}
3844
3845func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3846 cClient, err := dh.coreClient.GetCoreServiceClient()
3847 if err != nil || cClient == nil {
3848 return nil, err
3849 }
3850 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3851 defer cancel()
3852 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3853}
3854
3855func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3856 cClient, err := dh.coreClient.GetCoreServiceClient()
3857 if err != nil || cClient == nil {
3858 return err
3859 }
3860 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3861 defer cancel()
3862 _, err = cClient.DeviceUpdate(subCtx, device)
3863 return err
3864}
3865
khenaidoodc2116e2021-10-19 17:33:19 -04003866func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003867 cClient, err := dh.coreClient.GetCoreServiceClient()
3868 if err != nil || cClient == nil {
3869 return nil, err
3870 }
3871 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3872 defer cancel()
3873 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3874}
3875
khenaidoodc2116e2021-10-19 17:33:19 -04003876func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003877 cClient, err := dh.coreClient.GetCoreServiceClient()
3878 if err != nil || cClient == nil {
3879 return err
3880 }
3881 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3882 defer cancel()
3883 _, err = cClient.SendPacketIn(subCtx, pkt)
3884 return err
3885}
3886
3887func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3888 cClient, err := dh.coreClient.GetCoreServiceClient()
3889 if err != nil || cClient == nil {
3890 return err
3891 }
3892 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3893 defer cancel()
3894 _, err = cClient.PortCreated(subCtx, port)
3895 return err
3896}
3897
khenaidoodc2116e2021-10-19 17:33:19 -04003898func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003899 cClient, err := dh.coreClient.GetCoreServiceClient()
3900 if err != nil || cClient == nil {
3901 return err
3902 }
3903 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3904 defer cancel()
3905 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3906 return err
3907}
3908
khenaidoodc2116e2021-10-19 17:33:19 -04003909func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003910 cClient, err := dh.coreClient.GetCoreServiceClient()
3911 if err != nil || cClient == nil {
3912 return err
3913 }
3914 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3915 defer cancel()
3916 _, err = cClient.PortStateUpdate(subCtx, portState)
3917 return err
3918}
3919
khenaidoodc2116e2021-10-19 17:33:19 -04003920func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003921 cClient, err := dh.coreClient.GetCoreServiceClient()
3922 if err != nil || cClient == nil {
3923 return nil, err
3924 }
3925 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3926 defer cancel()
3927 return cClient.GetDevicePort(subCtx, portFilter)
3928}
3929
nikesh.krishnanc8473432023-06-14 12:14:54 +05303930func (dh *DeviceHandler) getAllPortsFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Ports, error) {
3931 cClient, err := dh.coreClient.GetCoreServiceClient()
3932 if err != nil || cClient == nil {
3933 return nil, err
3934 }
3935 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3936 defer cancel()
3937 return cClient.GetPorts(subCtx, portFilter)
3938}
3939
khenaidoo106c61a2021-08-11 18:05:46 -04003940/*
3941Helper functions to communicate with child adapter
3942*/
3943
khenaidoodc2116e2021-10-19 17:33:19 -04003944func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003945 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3946 if err != nil || aClient == nil {
3947 return err
3948 }
3949 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3950 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3951 defer cancel()
3952 _, err = aClient.OmciIndication(subCtx, response)
3953 return err
3954}
3955
khenaidoodc2116e2021-10-19 17:33:19 -04003956func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003957 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3958 if err != nil || aClient == nil {
3959 return err
3960 }
3961 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3962 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3963 defer cancel()
3964 _, err = aClient.OnuIndication(subCtx, onuInd)
3965 return err
3966}
3967
khenaidoodc2116e2021-10-19 17:33:19 -04003968func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003969 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3970 if err != nil || aClient == nil {
3971 return err
3972 }
3973 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3974 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3975 defer cancel()
3976 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3977 return err
3978}
3979
khenaidoodc2116e2021-10-19 17:33:19 -04003980func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003981 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3982 if err != nil || aClient == nil {
3983 return err
3984 }
3985 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3986 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3987 defer cancel()
3988 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3989 return err
3990}
3991
khenaidoodc2116e2021-10-19 17:33:19 -04003992func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003993 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3994 if err != nil || aClient == nil {
3995 return err
3996 }
3997 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3998 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3999 defer cancel()
4000 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
4001 return err
4002}
4003
4004/*
4005Helper functions for remote communication
4006*/
4007
4008// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
4009// supports is deleted
4010func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
4011 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
4012
4013 dh.lockChildAdapterClients.Lock()
4014 defer dh.lockChildAdapterClients.Unlock()
4015 if _, ok := dh.childAdapterClients[endpoint]; ok {
4016 // Already set
4017 return nil
4018 }
4019
4020 // Setup child's adapter grpc connection
4021 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05004022 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
4023 dh.cfg.AdapterEndpoint,
4024 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05004025 "onu_inter_adapter_service.OnuInterAdapterService",
4026 dh.onuInterAdapterRestarted,
4027 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004028 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
4029 return err
4030 }
nikesh.krishnand9812542023-08-01 18:31:39 +05304031 retryCodes := []codes.Code{
4032 codes.Unavailable, // server is currently unavailable
4033 codes.DeadlineExceeded, // deadline for the operation was exceeded
4034 }
4035 backoffCtxOption := grpc_retry.WithBackoff(grpc_retry.BackoffLinearWithJitter(dh.cfg.PerRPCRetryTimeout, 0.2))
4036 grpcRetryOptions := grpc_retry.UnaryClientInterceptor(grpc_retry.WithMax(dh.cfg.MaxRetries), grpc_retry.WithPerRetryTimeout(dh.cfg.PerRPCRetryTimeout), grpc_retry.WithCodes(retryCodes...), backoffCtxOption)
khenaidoo106c61a2021-08-11 18:05:46 -04004037
nikesh.krishnand9812542023-08-01 18:31:39 +05304038 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler, grpcRetryOptions)
khenaidoo106c61a2021-08-11 18:05:46 -04004039 // Wait until we have a connection to the child adapter.
4040 // Unlimited retries or until context expires
4041 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
4042 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
4043 for {
4044 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
4045 if err == nil && client != nil {
4046 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
4047 break
4048 }
4049 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
4050 // Backoff
4051 if err = backoff.Backoff(subCtx); err != nil {
4052 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
4053 break
4054 }
4055 }
4056 return nil
4057}
4058
khenaidoodc2116e2021-10-19 17:33:19 -04004059func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04004060
4061 // First check from cache
4062 dh.lockChildAdapterClients.RLock()
4063 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4064 dh.lockChildAdapterClients.RUnlock()
4065 return cgClient.GetOnuInterAdapterServiceClient()
4066 }
4067 dh.lockChildAdapterClients.RUnlock()
4068
4069 // Set the child connection - can occur on restarts
4070 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
4071 err := dh.setupChildInterAdapterClient(ctx, endpoint)
4072 cancel()
4073 if err != nil {
4074 return nil, err
4075 }
4076
4077 // Get the child client now
4078 dh.lockChildAdapterClients.RLock()
4079 defer dh.lockChildAdapterClients.RUnlock()
4080 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
4081 return cgClient.GetOnuInterAdapterServiceClient()
4082 }
4083 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
4084}
4085
4086func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
4087 dh.lockChildAdapterClients.Lock()
4088 defer dh.lockChildAdapterClients.Unlock()
4089 for key, client := range dh.childAdapterClients {
4090 client.Stop(ctx)
4091 delete(dh.childAdapterClients, key)
4092 }
4093}
4094
khenaidooefff76e2021-12-15 16:51:30 -05004095// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
4096func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
4097 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04004098 return nil
4099}
4100
khenaidooefff76e2021-12-15 16:51:30 -05004101// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
4102func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
4103 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04004104 return nil
4105 }
khenaidooefff76e2021-12-15 16:51:30 -05004106 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04004107}
Girish Gowdra950326e2021-11-05 12:43:24 -07004108
4109func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
4110 dh.lockDevice.Lock()
4111 defer dh.lockDevice.Unlock()
4112 dh.isDeviceDeletionInProgress = flag
4113}
4114
4115func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
4116 dh.lockDevice.RLock()
4117 defer dh.lockDevice.RUnlock()
4118 return dh.isDeviceDeletionInProgress
4119}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08004120
4121// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
4122// Returns false if waiting timed out.
4123func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
4124 c := make(chan struct{})
4125 go func() {
4126 defer close(c)
4127 wg.Wait()
4128 }()
4129 select {
4130 case <-c:
4131 return true // completed normally
4132 case <-time.After(timeout):
4133 return false // timed out
4134 }
4135}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05304136
4137func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
4138 val, err := json.Marshal(signature)
4139 if err != nil {
4140 logger.Error(ctx, "failed-to-marshal")
4141 return
4142 }
4143 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
4144 logger.Error(ctx, "failed-to-store-hearbeat-signature")
4145 }
4146}
4147
4148func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
4149 var signature uint32
4150
4151 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
4152 if er == nil {
4153 if Value != nil {
4154 Val, er := kvstore.ToByte(Value.Value)
4155 if er != nil {
4156 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
4157 return signature
4158 }
4159 if er = json.Unmarshal(Val, &signature); er != nil {
4160 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
4161 return signature
4162 }
4163 }
4164 }
4165 return signature
4166}