blob: 76f05da3d59077880409ff1ac9b1a8dc65ec58e6 [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
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
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053024 "encoding/json"
Girish Gowdra491a9c62021-01-06 16:43:07 -080025 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "fmt"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
Elia Battiston599d25f2022-02-16 14:49:08 +010033 "github.com/opencord/voltha-lib-go/v7/pkg/db"
34 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
35
khenaidoo106c61a2021-08-11 18:05:46 -040036 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040037
Matteo Scandolo945e4012019-12-12 14:16:11 -080038 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070039 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000040 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
41 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040042 "github.com/opencord/voltha-lib-go/v7/pkg/config"
43 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
44 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
45 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070046 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040047 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080048
khenaidoo106c61a2021-08-11 18:05:46 -040049 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053050 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080051 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040052 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040053 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040054 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040055 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
56 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040057 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
58 oop "github.com/opencord/voltha-protos/v5/go/openolt"
59 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070060 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040061 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040062 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053063)
64
salmansiddiqui7ac62132019-08-22 03:58:50 +000065// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040066const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080067 InvalidPort = 0xffffffff
68 MaxNumOfGroupHandlerChannels = 256
69
70 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
71 McastFlowOrGroupModify = "McastFlowOrGroupModify"
72 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050073 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010074
75 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053076 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040077)
78
Phaneendra Manda4c62c802019-03-06 21:37:49 +053079//DeviceHandler will interact with the OLT device.
80type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040081 cm *config.ConfigManager
82 device *voltha.Device
83 cfg *conf.AdapterFlags
84 coreClient *vgrpc.Client
85 childAdapterClients map[string]*vgrpc.Client
86 lockChildAdapterClients sync.RWMutex
87 EventProxy eventif.EventProxy
88 openOLT *OpenOLT
khenaidooefff76e2021-12-15 16:51:30 -050089 exitChannel chan struct{}
khenaidoo106c61a2021-08-11 18:05:46 -040090 lockDevice sync.RWMutex
91 Client oop.OpenoltClient
92 transitionMap *TransitionMap
93 clientCon *grpc.ClientConn
94 flowMgr []*OpenOltFlowMgr
95 groupMgr *OpenOltGroupMgr
96 eventMgr *OpenOltEventMgr
97 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053098 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070099
100 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530101
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700102 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
103 // if the value is true that means the OnuDiscovery indication
104 // is currently being processed and thus we can ignore concurrent requests
105 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
106 // if we do it means something went wrong and we need to retry
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700107 discOnus sync.Map
108 onus sync.Map
109 portStats *OpenOltStatisticsMgr
110 metrics *pmmetrics.PmMetrics
111 stopCollector chan bool
112 stopHeartbeatCheck chan bool
113 activePorts sync.Map
114 stopIndications chan bool
115 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700116
Mahir Gunyelb0046752021-02-26 13:51:05 -0800117 totalPonPorts uint32
118 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
119 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800120
121 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
122 // 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 -0700123 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
124 stopMcastHandlerRoutine []chan bool
125 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000126
127 adapterPreviouslyConnected bool
128 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700129
130 isDeviceDeletionInProgress bool
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530131 heartbeatSignature uint32
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700132}
133
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700135type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400136 deviceID string
137 deviceType string
138 serialNumber string
139 onuID uint32
140 intfID uint32
141 proxyDeviceID string
142 losRaised bool
143 rdiRaised bool
144 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700145}
146
Mahir Gunyelb0046752021-02-26 13:51:05 -0800147type onuIndicationMsg struct {
148 ctx context.Context
149 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800150}
151
152type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800153 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800154 stopChannel chan struct{}
155}
156
Girish Gowdra491a9c62021-01-06 16:43:07 -0800157//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
158//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
159//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
160//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
161type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400162 ctx context.Context // Flow/group handler context
163 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
164 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
165 group *of.OfpGroupEntry // Group message (can be nil or valid group)
166 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800167}
168
Naga Manjunath7615e552019-10-11 22:35:47 +0530169var pmNames = []string{
170 "rx_bytes",
171 "rx_packets",
172 "rx_mcast_packets",
173 "rx_bcast_packets",
174 "tx_bytes",
175 "tx_packets",
176 "tx_mcast_packets",
177 "tx_bcast_packets",
178}
179
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700180//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400181func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700182 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700183 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700184 device.deviceType = deviceTp
185 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700186 device.onuID = onuID
187 device.intfID = intfID
188 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530189 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400190 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700191 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530192}
193
194//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400195func 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 -0700196 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530197 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800198 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400199 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400200 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700201 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700202 dh.device = cloned
203 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500204 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700205 dh.lockDevice = sync.RWMutex{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800206 dh.stopCollector = make(chan bool, 2) // TODO: Why buffered?
207 dh.stopHeartbeatCheck = make(chan bool, 2) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530208 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 -0500209 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800210 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800211 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400212 dh.childAdapterClients = make(map[string]*vgrpc.Client)
213 dh.cfg = cfg
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530214 kvStoreDevicePath := fmt.Sprintf(dh.cm.Backend.PathPrefix, "/%s/", dh.device.Id)
215 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, kvStoreDevicePath)
216 if dh.kvStore == nil {
217 logger.Error(ctx, "Failed to setup KV store")
218 return nil
219 }
220
Girish Gowdra491a9c62021-01-06 16:43:07 -0800221 // Create a slice of buffered channels for handling concurrent mcast flow/group.
222 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700223 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
224 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800225 for i := range dh.incomingMcastFlowOrGroup {
226 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800227 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800228 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
229 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
230 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
231 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700232 dh.mcastHandlerRoutineActive[i] = true
233 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800234 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700235 //TODO initialize the support classes.
236 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530237}
238
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530239func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
240 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
241 switch storeType {
242 case "etcd":
243 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
244 }
245 return nil, errors.New("unsupported-kv-store")
246}
247
248// SetKVClient sets the KV client and return a kv backend
249func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
250 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
251 if err != nil {
252 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
253 return nil
254 }
255
256 kvbackend := &db.Backend{
257 Client: kvClient,
258 StoreType: backend,
259 Address: addr,
260 Timeout: rsrcMgr.KvstoreTimeout,
261 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
262
263 return kvbackend
264}
265
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530266// start save the device to the data model
267func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700268 dh.lockDevice.Lock()
269 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000270 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700271 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000272 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530273}
274
khenaidooefff76e2021-12-15 16:51:30 -0500275// Stop stops the device handler
276func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700277 dh.lockDevice.Lock()
278 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000279 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500280 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400281
khenaidooefff76e2021-12-15 16:51:30 -0500282 // Delete (which will stop also) all grpc connections to the child adapters
283 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000284 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530285}
286
ssiddiqui04386ee2021-08-23 21:58:25 +0530287func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
288 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
289 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
290 if pooledIntfID == intfID {
291 return resourceRanges.GetTechnology()
292 }
293 }
294 }
295 return ""
296}
297
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400298func macifyIP(ip net.IP) string {
299 if len(ip) > 0 {
300 oct1 := strconv.FormatInt(int64(ip[12]), 16)
301 oct2 := strconv.FormatInt(int64(ip[13]), 16)
302 oct3 := strconv.FormatInt(int64(ip[14]), 16)
303 oct4 := strconv.FormatInt(int64(ip[15]), 16)
304 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
305 }
306 return ""
307}
308
Neha Sharma96b7bf22020-06-15 10:37:32 +0000309func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400310 var genmac string
311 var addr net.IP
312 var ips []string
313 var err error
314
Neha Sharma96b7bf22020-06-15 10:37:32 +0000315 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400316
317 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000318 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400319
320 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400322 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000323 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400324 }
325 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000326 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530327 log.Fields{"host": ips[0],
328 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400329 return genmac, nil
330 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000331 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400332 }
333
334 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000335 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530336 log.Fields{"host": host,
337 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400338 return genmac, nil
339}
340
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530341func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700342 slist := strings.Split(mac, ":")
343 result := make([]uint32, len(slist))
344 var err error
345 var tmp int64
346 for index, val := range slist {
347 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
348 return []uint32{1, 2, 3, 4, 5, 6}
349 }
350 result[index] = uint32(tmp)
351 }
352 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530353}
354
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700355//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 -0800356func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530357
David K. Bainbridge794735f2020-02-11 21:01:37 -0800358 switch portType {
359 case voltha.Port_ETHERNET_NNI:
360 return fmt.Sprintf("nni-%d", portNum), nil
361 case voltha.Port_PON_OLT:
362 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700363 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800364
Girish Kumarf26e4882020-03-05 06:49:10 +0000365 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530366}
367
Elia Battiston596406d2022-02-02 12:19:00 +0100368func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
369 if speedMbps == 0 {
370 //In case it was not set in the indication
371 //and no other value was provided
372 speedMbps = defaultPortSpeedMbps
373 }
374
375 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
376 switch speedMbps {
377 case 1000000:
378 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
379 case 100000:
380 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
381 case 40000:
382 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
383 case 10000:
384 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
385 case 1000:
386 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
387 case 100:
388 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
389 case 10:
390 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
391 }
392
393 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
394
395 port := &of.OfpPort{
396 HwAddr: macAddressToUint32Array(macAddress),
397 Config: 0,
398 State: uint32(of.OfpPortState_OFPPS_LIVE),
399 Curr: capacity,
400 Advertised: capacity,
401 Peer: capacity,
402 CurrSpeed: speedMbps * 1000, //kbps
403 MaxSpeed: speedMbps * 1000, //kbps
404 }
405
406 return port
407}
408
409func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000410 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700411 if state == "up" {
412 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500413 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500414 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700415 } else {
416 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500417 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700418 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700419 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400420 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800421 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000422 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400423 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500424
khenaidoo106c61a2021-08-11 18:05:46 -0400425 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400426 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400427 DeviceId: dh.device.Id,
428 Port: portNum,
429 })
430 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000431 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400432 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400433 DeviceId: dh.device.Id,
434 PortType: portType,
435 PortNo: portNum,
436 OperStatus: operStatus})
437 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400438 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
439 "device-id": dh.device.Id,
440 "port-type": portType,
441 "port-number": portNum,
442 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500443 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400444 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500445 }
khenaidoo106c61a2021-08-11 18:05:46 -0400446
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400447 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400448 port = &voltha.Port{
449 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700450 PortNo: portNum,
451 Label: label,
452 Type: portType,
453 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100454 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700455 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000456 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700457 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400458 err = dh.createPortInCore(ctx, port)
459 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000460 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800461 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000462 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400463 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000464 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530465 return nil
466}
467
Kent Hagermane6ff1012020-07-14 15:07:53 -0400468func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400469 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530470 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400471 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
472 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530473 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800474 dh.lockDevice.Lock()
475 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530476 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530477}
478
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700479// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530480// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000482 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700483 defer func() {
484 dh.lockDevice.Lock()
485 dh.isReadIndicationRoutineActive = false
486 dh.lockDevice.Unlock()
487 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700488 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700489 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700490 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700491 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400492
David Bainbridgef5879ca2019-12-13 21:17:54 +0000493 // Create an exponential backoff around re-enabling indications. The
494 // maximum elapsed time for the back off is set to 0 so that we will
495 // continue to retry. The max interval defaults to 1m, but is set
496 // here for code clarity
497 indicationBackoff := backoff.NewExponentialBackOff()
498 indicationBackoff.MaxElapsedTime = 0
499 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700500
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700501 dh.lockDevice.Lock()
502 dh.isReadIndicationRoutineActive = true
503 dh.lockDevice.Unlock()
504
Girish Gowdra3f974912020-03-23 20:35:18 -0700505Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700506 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400507 select {
508 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000509 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700510 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400511 default:
512 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100513
514 select {
515 case <-indications.Context().Done():
516 if err != nil {
517 logger.Warnw(ctx, "error-during-enable-indications",
518 log.Fields{"err": err,
519 "device-id": dh.device.Id})
520 }
521
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400522 // Use an exponential back off to prevent getting into a tight loop
523 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100524 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
525 "device-id": dh.device.Id,
526 "duration": duration,
527 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400528 if duration == backoff.Stop {
529 // If we reach a maximum then warn and reset the backoff
530 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100531 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530532 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530533 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400534 indicationBackoff.Reset()
535 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700536
537 // On failure process a backoff timer while watching for stopIndications
538 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700539 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700540 select {
541 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000542 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700543 if !backoffTimer.Stop() {
544 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700545 }
546 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700547 case <-backoffTimer.C:
548 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700549 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700550 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
551 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400552 }
553 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100554 default:
555 if err != nil {
556 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530557 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530558 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100559 // Close the stream, and re-initialize it
560 if err = indications.CloseSend(); err != nil {
561 // Ok to ignore here, because we landed here due to a problem on the stream
562 // In all probability, the closeSend call may fail
563 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
564 log.Fields{"err": err,
565 "device-id": dh.device.Id})
566 }
567 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
568 return err
569 }
570 // once we re-initialized the indication stream, continue to read indications
571 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700572 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100573 // Reset backoff if we have a successful receive
574 indicationBackoff.Reset()
575 // When OLT is admin down, ignore all indications.
576 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
577 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
578 log.Fields{"indication": indication,
579 "device-id": dh.device.Id})
580 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700581 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100582 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530583 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700584 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700585 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700586 // Close the send stream
587 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700588
Girish Gowdra3f974912020-03-23 20:35:18 -0700589 return nil
590}
591
592func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700593 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700594 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
595 if err != nil {
596 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
597 }
598 if indications == nil {
599 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
600 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700601 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700602 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400603}
604
605// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
606func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
607 switch indication.Data.(type) {
608 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
609 return true
610
611 default:
612 return false
613 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700614}
615
David K. Bainbridge794735f2020-02-11 21:01:37 -0800616func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700617 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000618 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530619 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700620 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530621 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000623 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000624 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530625 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000626 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800627 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000628 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800629 }
630 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700631}
632
David K. Bainbridge794735f2020-02-11 21:01:37 -0800633// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530634func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700635 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700636 switch indication.Data.(type) {
637 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000638 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
639 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700640 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 -0800641 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400642 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800643 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700644 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000645 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
646 defer span.Finish()
647
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700648 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800649 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100650 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400651 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800652 }
653 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000654 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000656 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
657 defer span.Finish()
658
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700659 intfOperInd := indication.GetIntfOperInd()
660 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800661 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100662 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400663 _ = 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 -0800664 }
665 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700666 } else if intfOperInd.GetType() == "pon" {
667 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
668 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800669 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100670 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400671 _ = 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 -0800672 }
673 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000674 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700675 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000676 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530677 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530678 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700679 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000680 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
681 defer span.Finish()
682
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700683 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000684 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800685 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800686 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700687 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000688 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
689 defer span.Finish()
690
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000692 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800693 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800694 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000696 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
697 defer span.Finish()
698
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700699 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000700 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 -0800701 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400703 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800704 }
705 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700706 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000707 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
708 defer span.Finish()
709
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700710 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000711 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700712 "intf-type": pktInd.IntfId,
713 "intf-id": pktInd.IntfId,
714 "gem-port-id": pktInd.GemportId,
715 "port-no": pktInd.PortNo,
716 "device-id": dh.device.Id,
717 })
718
719 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000720 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700721 "intf-type": pktInd.IntfId,
722 "intf-id": pktInd.IntfId,
723 "gem-port-id": pktInd.GemportId,
724 "port-no": pktInd.PortNo,
725 "packet": hex.EncodeToString(pktInd.Pkt),
726 "device-id": dh.device.Id,
727 })
728 }
729
David K. Bainbridge794735f2020-02-11 21:01:37 -0800730 go func() {
731 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400732 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800733 }
734 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700735 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000736 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
737 defer span.Finish()
738
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700740 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700741 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000742 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
743 defer span.Finish()
744
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700745 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000746 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000748 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
749 defer span.Finish()
750
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700751 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000752 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
753 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700754 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530755}
756
757// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530758func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530759 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000760 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530761
Girish Gowdra618fa572021-09-01 17:19:29 -0700762 // instantiate the mcast handler routines.
763 for i := range dh.incomingMcastFlowOrGroup {
764 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
765 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
766 if !dh.mcastHandlerRoutineActive[i] {
767 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
768 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
769 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
770 // for incoming mcast flow/group to be processed serially.
771 dh.mcastHandlerRoutineActive[i] = true
772 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
773 }
774 }
775
Girish Gowdru0c588b22019-04-23 23:24:56 -0400776 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400777 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400778 DeviceId: dh.device.Id,
779 OperStatus: voltha.OperStatus_ACTIVE,
780 ConnStatus: voltha.ConnectStatus_REACHABLE,
781 }); err != nil {
782 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400783 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000784
785 //Clear olt communication failure event
786 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
787 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700788 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000789 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
790
Girish Gowdru0c588b22019-04-23 23:24:56 -0400791 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530792}
793
794// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530795func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000796 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400797
khenaidoo106c61a2021-08-11 18:05:46 -0400798 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400799 if err != nil || device == nil {
800 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000801 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400802 }
803
804 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400805
806 //Update the device oper state and connection status
807 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800808 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400809 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800810 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400811
khenaidoodc2116e2021-10-19 17:33:19 -0400812 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400813 DeviceId: cloned.Id,
814 OperStatus: cloned.OperStatus,
815 ConnStatus: cloned.ConnectStatus,
816 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000817 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400818 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400819
820 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400821 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400822 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000823 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400824 }
825 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400826 // Update onu state as down in onu adapter
827 onuInd := oop.OnuIndication{}
828 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400829
830 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
831 if err != nil {
832 return err
833 }
834 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400835 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400836 DeviceId: onuDevice.Id,
837 OnuIndication: &onuInd,
838 })
839 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800840 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400841 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400842 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800843 "onu-indicator": onuInd,
844 "device-type": onuDevice.Type,
845 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700846 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800847 } else {
848 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 -0700849 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400850 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800851 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700852 /* Discovered ONUs entries need to be cleared , since after OLT
853 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530854 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800855 dh.lockDevice.Unlock()
856
Neha Sharma96b7bf22020-06-15 10:37:32 +0000857 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700858 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530859}
860
861// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530862func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400863 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000864
865 // if the connection is already available, close the previous connection (olt reboot case)
866 if dh.clientCon != nil {
867 if err = dh.clientCon.Close(); err != nil {
868 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
869 } else {
870 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
871 }
872 }
873
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530874 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +0000875 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000876 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
877 grpc.WithInsecure(),
878 grpc.WithBlock(),
879 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000880 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000881 )),
882 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000883 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000884 )))
885
886 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530887 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530888 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000889 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400890 }
891 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530892}
893
894// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530895func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400896 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530897 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400898 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530899}
900
901// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530902func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530903 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000904 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400905
906 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400907 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530908 if err != nil || device == nil {
909 /*TODO: needs to handle error scenarios */
910 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
911 }
912 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000913 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400914
915 cloned := proto.Clone(device).(*voltha.Device)
916 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
917 cloned.OperStatus = voltha.OperStatus_UNKNOWN
918 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400919
khenaidoodc2116e2021-10-19 17:33:19 -0400920 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400921 DeviceId: cloned.Id,
922 OperStatus: cloned.OperStatus,
923 ConnStatus: cloned.ConnectStatus,
924 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530925 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 -0400926 }
927
Chaitrashree G S44124192019-08-07 20:21:36 -0400928 // 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 +0530929 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400930 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530931 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400932 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400933 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
934 // all the modules initialized and ready to handle incoming ONUs.
935
Thomas Lee S985938d2020-05-04 11:40:41 +0530936 err = dh.initializeDeviceHandlerModules(ctx)
937 if err != nil {
938 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 -0400939 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400940
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700941 go startHeartbeatCheck(ctx, dh)
942
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400943 return nil
944 }
945
khenaidoo106c61a2021-08-11 18:05:46 -0400946 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400947 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400948 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400949 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400950 }
khenaidoo106c61a2021-08-11 18:05:46 -0400951 dh.populateActivePorts(ctx, ports.Items)
952 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400953 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400954 }
955
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400956 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530957 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 -0400958 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530959
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000961
962 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000963 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000964 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700965
966 go startHeartbeatCheck(ctx, dh)
967
cuilin20187b2a8c32019-03-26 19:52:28 -0700968 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530969}
970
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400971func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700972 var err error
973 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400974
975 if err != nil {
976 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
977 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700978 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
979 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +0000980 // +1 is for NNI
981 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
982 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700983 var i uint32
yasin saplid0566272021-12-21 09:10:30 +0000984 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
985 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
986 // There is only one NNI manager since multiple NNI is not supported for now
987 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700988 // Instantiate resource manager
989 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 -0700990 return olterrors.ErrResourceManagerInstantiating
991 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400992 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700993 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
994 // the KV store to manage mcast group data. Provide the first instance (0th index)
995 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
996 return olterrors.ErrGroupManagerInstantiating
997 }
yasin saplid0566272021-12-21 09:10:30 +0000998 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700999 // Instantiate flow manager
1000 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
1001 return olterrors.ErrFlowManagerInstantiating
1002 }
Girish Gowdra76a1b092021-07-28 10:07:04 -07001003 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001004 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001005 /* TODO: Instantiate Alarm , stats , BW managers */
1006 /* Instantiating Event Manager to handle Alarms and KPIs */
1007 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1008
1009 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001010 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001011
1012 return nil
1013
1014}
1015
Neha Sharma96b7bf22020-06-15 10:37:32 +00001016func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001017 var err error
1018 var deviceInfo *oop.DeviceInfo
1019
Neha Sharma8f4e4322020-08-06 10:51:53 +00001020 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001021
1022 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001023 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001024 }
1025 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001026 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001027 }
1028
Neha Sharma96b7bf22020-06-15 10:37:32 +00001029 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001030 dh.device.Root = true
1031 dh.device.Vendor = deviceInfo.Vendor
1032 dh.device.Model = deviceInfo.Model
1033 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1034 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1035 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1036
1037 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001038 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001039 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001040 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001041 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001042 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001043 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001044 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001045 dh.device.MacAddress = genmac
1046 } else {
1047 dh.device.MacAddress = deviceInfo.DeviceId
1048 }
1049
1050 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001051 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001052 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001053 }
1054
1055 return deviceInfo, nil
1056}
1057
Neha Sharma96b7bf22020-06-15 10:37:32 +00001058func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001059 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301060 for {
1061 select {
1062 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001063 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301064 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001065 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001066
khenaidoo106c61a2021-08-11 18:05:46 -04001067 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001068 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001069 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001070 continue
1071 }
khenaidoo106c61a2021-08-11 18:05:46 -04001072 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301073 // NNI Stats
1074 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001075 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301076 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001077 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001078 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001079 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301080 }
1081 // PON Stats
1082 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001083 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301084 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1085 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001086 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001087 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301088 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001089 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001090
yasin sapli9e4c5092022-02-01 13:52:33 +00001091 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001092 if len(onuGemInfoLst) > 0 {
1093 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001094 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001095 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301096 }
1097 }
1098 }
1099}
1100
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001101//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301102func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001103 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001104 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301105 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301106
1107 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001108 cgClient, err := dh.coreClient.GetCoreServiceClient()
1109 if err != nil {
1110 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1111 return
1112 }
1113
1114 // Now, set the initial PM configuration for that device
1115 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001116 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301117 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301118}
1119
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001120//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001121func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1122 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001123 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301124 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001125 HwDesc: "open_pon",
1126 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001127 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001128 },
1129 SwitchFeatures: &of.OfpSwitchFeatures{
1130 NBuffers: 256,
1131 NTables: 2,
1132 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1133 of.OfpCapabilities_OFPC_TABLE_STATS |
1134 of.OfpCapabilities_OFPC_PORT_STATS |
1135 of.OfpCapabilities_OFPC_GROUP_STATS),
1136 },
1137 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301138}
1139
khenaidoo106c61a2021-08-11 18:05:46 -04001140// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001141func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001142 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001143 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001144 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001145 }
khenaidoo106c61a2021-08-11 18:05:46 -04001146 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001147}
1148
Neha Sharma96b7bf22020-06-15 10:37:32 +00001149func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001150 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 -07001151 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152 var deviceID string
1153 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001154 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001155
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001156 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001157 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001158 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 -07001159 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1160 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001161
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001162 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301163
1164 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1165
Neha Sharma96b7bf22020-06-15 10:37:32 +00001166 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 -07001167 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001168
khenaidoodc2116e2021-10-19 17:33:19 -04001169 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001170 ParentId: dh.device.Id,
1171 OnuId: omciInd.OnuId,
1172 ParentPortNo: ponPort,
1173 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001174 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301175 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001176 "intf-id": omciInd.IntfId,
1177 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001178 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001179 deviceType = onuDevice.Type
1180 deviceID = onuDevice.Id
1181 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001182 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001183 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001184 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001185 } else {
1186 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001187 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 +05301188 deviceType = onuInCache.(*OnuDevice).deviceType
1189 deviceID = onuInCache.(*OnuDevice).deviceID
1190 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001191 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001192 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001193
khenaidoodc2116e2021-10-19 17:33:19 -04001194 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001195 ParentDeviceId: proxyDeviceID,
1196 ChildDeviceId: deviceID,
1197 Message: omciInd.Pkt,
1198 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301199 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001200 "source": dh.openOLT.config.AdapterEndpoint,
1201 "device-type": deviceType,
1202 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001203 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001204 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001205 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001206 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301207}
1208
khenaidoo106c61a2021-08-11 18:05:46 -04001209// //ProcessInterAdapterMessage sends the proxied messages to the target device
1210// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1211// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001212// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001213// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001214// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001215// return dh.handleInterAdapterOmciMsg(ctx, msg)
1216// }
1217// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1218// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001219
kesavandb9f54fd2021-11-25 20:08:04 +05301220// ProxyOmciRequests sends the proxied OMCI message to the target device
1221func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
1222 if omciMsgs.GetProxyAddress() == nil {
1223 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1224 if err != nil {
1225 return olterrors.NewErrNotFound("onu", log.Fields{
1226 "parent-device-id": dh.device.Id,
1227 "child-device-id": omciMsgs.ChildDeviceId}, err)
1228 }
1229 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1230 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1231 return olterrors.NewErrCommunication("send-failed", log.Fields{
1232 "parent-device-id": dh.device.Id,
1233 "child-device-id": omciMsgs.ChildDeviceId}, err)
1234 }
1235 } else {
1236 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1237 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1238 return olterrors.NewErrCommunication("send-failed", log.Fields{
1239 "parent-device-id": dh.device.Id,
1240 "child-device-id": omciMsgs.ChildDeviceId}, err)
1241 }
1242 }
1243 return nil
1244}
1245
1246func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1247 var intfID uint32
1248 var onuID uint32
1249 var connectStatus common.ConnectStatus_Types
1250 if onuDevice != nil {
1251 intfID = onuDevice.ProxyAddress.GetChannelId()
1252 onuID = onuDevice.ProxyAddress.GetOnuId()
1253 connectStatus = onuDevice.ConnectStatus
1254 } else {
1255 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1256 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1257 connectStatus = omciMsgs.GetConnectStatus()
1258 }
1259 if connectStatus != voltha.ConnectStatus_REACHABLE {
1260 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1261
1262 return olterrors.NewErrCommunication("unreachable", log.Fields{
1263 "intf-id": intfID,
1264 "onu-id": onuID}, nil)
1265 }
1266
1267 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1268 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1269
1270 onuSecOmciMsgList := omciMsgs.GetMessages()
1271
1272 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1273
1274 var omciMessage *oop.OmciMsg
1275 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1276 hex.Encode(hexPkt, onuSecOmciMsg)
1277 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1278
1279 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1280 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1281 //https://jira.opencord.org/browse/VOL-4604
1282 transid := extractOmciTransactionID(onuSecOmciMsg)
1283 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1284 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1285
1286 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1287 if err != nil {
1288 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1289 "intf-id": intfID,
1290 "onu-id": onuID,
1291 "message": omciMessage}, err)
1292 }
1293 }
1294 return nil
1295}
1296
khenaidoo106c61a2021-08-11 18:05:46 -04001297// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001298func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001299 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 -07001300
1301 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001302 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001303 if err != nil {
1304 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001305 "parent-device-id": dh.device.Id,
1306 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001307 }
khenaidoo106c61a2021-08-11 18:05:46 -04001308 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1309 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001310 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001311 "parent-device-id": dh.device.Id,
1312 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001313 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001314 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001315 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1316 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001317 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001318 "parent-device-id": dh.device.Id,
1319 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001320 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001321 }
1322 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301323}
1324
khenaidoodc2116e2021-10-19 17:33:19 -04001325func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001326 var intfID uint32
1327 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001328 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001329 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001330 intfID = onuDevice.ProxyAddress.GetChannelId()
1331 onuID = onuDevice.ProxyAddress.GetOnuId()
1332 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001333 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001334 intfID = omciMsg.GetProxyAddress().GetChannelId()
1335 onuID = omciMsg.GetProxyAddress().GetOnuId()
1336 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001337 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001338 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001339 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 -08001340
Thomas Lee S94109f12020-03-03 16:39:29 +05301341 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001342 "intf-id": intfID,
1343 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001344 }
1345
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001346 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1347 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301348 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001349 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001350 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1351 hex.Encode(hexPkt, omciMsg.Message)
1352 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1353
1354 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1355 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1356 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001357 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001358 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001359
Neha Sharma8f4e4322020-08-06 10:51:53 +00001360 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301362 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001363 "intf-id": intfID,
1364 "onu-id": onuID,
1365 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001367 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001368}
1369
David K. Bainbridge794735f2020-02-11 21:01:37 -08001370func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301371 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 +00001372 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001373 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001374 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001375 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301376 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301377 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001378 st, _ := status.FromError(err)
1379 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001380 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1381
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001382 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301383 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001384 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001385 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001386 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001387 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001388 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001389}
1390
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301391//getChildDevice function can be used in general to get child device, if not found in cache the function will
1392//get from core and update the cache and return the child device.
1393func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1394 var InCacheOnuDev *OnuDevice
1395 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1396 if onuInCache.(*OnuDevice).serialNumber == sn {
1397 InCacheOnuDev = onuInCache.(*OnuDevice)
1398 return false
1399 }
1400 return true
1401 })
1402 //Got the onu device from cache return
1403 if InCacheOnuDev != nil {
1404 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1405 return InCacheOnuDev
1406 }
1407 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1408 ParentId: dh.device.Id,
1409 SerialNumber: sn,
1410 ParentPortNo: parentPortNo,
1411 })
1412 //No device found in core return nil
1413 if onuDevice == nil {
1414 return nil
1415 }
1416 onuID := onuDevice.ProxyAddress.OnuId
1417 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1418 onuKey := dh.formOnuKey(intfID, onuID)
1419
1420 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1421 dh.onus.Store(onuKey, onuDev)
1422 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1423 return onuDev
1424}
1425
1426func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001428 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301429 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001430
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301431 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1432 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1433 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1434 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1435 if onuDev != nil {
1436 var onuGemInfo *rsrcMgr.OnuGemInfo
1437 var err error
1438 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1439 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1440 return false, err
1441 }
1442 if onuGemInfo != nil {
1443 for _, uni := range onuGemInfo.UniPorts {
1444 uniID := plt.UniIDFromPortNum(uni)
1445 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1446 if len(tpIDs) != 0 {
1447 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1448 tpInstExists = true
1449 break
1450 }
1451 }
1452 }
1453 }
1454 return tpInstExists, nil
1455 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301456
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301457 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1458 ParentId: dh.device.Id,
1459 SerialNumber: sn,
1460 ParentPortNo: parentPortNo,
1461 })
1462 if onuDevice != nil {
1463 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1464 return true, nil
1465 }
1466 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1467
1468 return false, nil
1469
1470}
1471
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001472// processDiscONULOSClear clears the LOS Alarm if it's needed
1473func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301474 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001475 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301476
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001477 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1478 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1479 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1480 OnuLosRaise event sent for it */
1481 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1482 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1483 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1484 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1485 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1486 "currentIntfId": onuDiscInd.GetIntfId()})
1487 // TODO:: Should we need to ignore raising OnuLosClear event
1488 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301489 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001490 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1491 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1492 alarmInd.LosStatus = statusCheckOff
1493 go func() {
1494 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1495 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1496 }
1497 }()
1498 // stop iterating
1499 return false
1500 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301501 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001502 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301503}
1504
1505func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
1506 channelID := onuDiscInd.GetIntfId()
1507 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1508
1509 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
1510 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1511
1512 tpInstExists, errtp := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1513 if errtp != nil {
1514 return errtp
1515 }
1516 if tpInstExists {
1517 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001518 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001519 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001520 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001521 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1522
1523 // if the ONU existed, handle the LOS Alarm
1524 if existing {
1525
1526 if inProcess.(bool) {
1527 // if we're currently processing the ONU on a different thread, do nothing
1528 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1529 return nil
1530 }
1531 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1532 // then continue processing it
1533 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1534
1535 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301536 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001537
1538 defer func() {
1539 // once the function completes set the value to false so that
1540 // we know the processing has inProcess.
1541 // Note that this is done after checking if we are already processing
1542 // to avoid changing the value from a different thread
1543 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1544 dh.discOnus.Store(sn, false)
1545 }()
1546
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001547 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001548
1549 // check the ONU is already know to the OLT
1550 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001551 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001552 ParentId: dh.device.Id,
1553 SerialNumber: sn,
1554 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001555
1556 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001557 logger.Debugw(ctx, "core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001558 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001559 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 -08001560 switch e.Code() {
1561 case codes.Internal:
1562 // this probably means NOT FOUND, so just create a new device
1563 onuDevice = nil
1564 case codes.DeadlineExceeded:
1565 // if the call times out, cleanup and exit
1566 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001567 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001568 }
1569 }
1570 }
1571
1572 if onuDevice == nil {
1573 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001574 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001575 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001576 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001577 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001578
Neha Sharma96b7bf22020-06-15 10:37:32 +00001579 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001580
1581 if err != nil {
1582 // if we can't create an ID in resource manager,
1583 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001584 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001585 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001586 "pon-intf-id": ponintfid,
1587 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001588 }
1589
khenaidoodc2116e2021-10-19 17:33:19 -04001590 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001591 ParentId: dh.device.Id,
1592 ParentPortNo: parentPortNo,
1593 ChannelId: channelID,
1594 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1595 SerialNumber: sn,
1596 OnuId: onuID,
1597 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001598 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001599 dh.resourceMgr[ponintfid].FreeonuID(ctx, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301600 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001601 "pon-intf-id": ponintfid,
1602 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001603 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001604 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001605 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001606 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001607 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301608 log.Fields{"onuDevice": onuDevice,
1609 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001610 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301611 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001612 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001613
khenaidoo106c61a2021-08-11 18:05:46 -04001614 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1615 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1616 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1617 cancel()
1618 if err != nil {
1619 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1620 }
1621
Matteo Scandolo945e4012019-12-12 14:16:11 -08001622 // we can now use the existing ONU Id
1623 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001624 //Insert the ONU into cache to use in OnuIndication.
1625 //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 +00001626 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001627 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301628 "intfId": onuDiscInd.GetIntfId(),
1629 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001630 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001631
khenaidoo106c61a2021-08-11 18:05:46 -04001632 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301633 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001634 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301635 log.Fields{"onu": onuDev,
1636 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001637
khenaidoodc2116e2021-10-19 17:33:19 -04001638 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001639 DeviceId: onuDevice.Id,
1640 ParentDeviceId: dh.device.Id,
1641 OperStatus: common.OperStatus_DISCOVERED,
1642 ConnStatus: common.ConnectStatus_REACHABLE,
1643 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301644 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001645 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001646 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001647 }
khenaidoo106c61a2021-08-11 18:05:46 -04001648
Neha Sharma96b7bf22020-06-15 10:37:32 +00001649 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001650 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301651 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001652 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001653 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001654 }
1655 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001656}
1657
Mahir Gunyelb0046752021-02-26 13:51:05 -08001658func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001659
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001660 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001661 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001662 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001663 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001664 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301665 log.Fields{"onuId": onuInd.OnuId,
1666 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301667 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001668 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001669 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301670
David K. Bainbridge794735f2020-02-11 21:01:37 -08001671 errFields := log.Fields{"device-id": dh.device.Id}
1672
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301673 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1674
Mahir Gunyele77977b2019-06-27 05:36:22 -07001675 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1676 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001677 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001678 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001679 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001680 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1681 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001682 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001683 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001684 errFields["onu-id"] = onuInd.OnuId
1685 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001686 }
khenaidoodc2116e2021-10-19 17:33:19 -04001687 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001688 ParentId: dh.device.Id,
1689 SerialNumber: serialNumber,
1690 OnuId: onuInd.OnuId,
1691 ParentPortNo: ponPort,
1692 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001693 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001694
David K. Bainbridge794735f2020-02-11 21:01:37 -08001695 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001696 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001697 }
1698
David K. Bainbridge794735f2020-02-11 21:01:37 -08001699 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001700 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001701 "previousIntfId": onuDevice.ParentPortNo,
1702 "currentIntfId": ponPort})
1703 }
1704
1705 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001706 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301707 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1708 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301709 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001710 }
1711 if !foundInCache {
1712 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1713
khenaidoo106c61a2021-08-11 18:05:46 -04001714 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 -08001715
1716 }
kesavand7cf3a052020-08-28 12:49:18 +05301717 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001718 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001719 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301720 }
1721 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001722 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001723 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001724 }
1725 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001726}
1727
Neha Sharma96b7bf22020-06-15 10:37:32 +00001728func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001729 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 -07001730 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1731 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1732 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1733 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001734 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001735 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1736 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001737 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001738 onuInd.OperState = "down"
1739 }
1740 }
1741
David K. Bainbridge794735f2020-02-11 21:01:37 -08001742 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001743 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001744 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 -04001745
khenaidoodc2116e2021-10-19 17:33:19 -04001746 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001747 DeviceId: onuDevice.Id,
1748 OnuIndication: onuInd,
1749 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001750 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301751 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001752 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001753 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001754 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001755 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001756 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001757 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001758 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001759 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001760 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001761}
1762
cuilin20187b2a8c32019-03-26 19:52:28 -07001763func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1764 if serialNum != nil {
1765 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001766 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001767 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001768}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001769func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1770 decodedStr, err := hex.DecodeString(serialNum[4:])
1771 if err != nil {
1772 return nil, err
1773 }
1774 return &oop.SerialNumber{
1775 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001776 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001777 }, nil
1778}
cuilin20187b2a8c32019-03-26 19:52:28 -07001779
1780func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001781 if len(vendorSpecific) > 3 {
1782 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1783 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1784 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1785 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1786 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1787 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1788 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1789 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1790 return tmp
1791 }
1792 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001793}
1794
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001795//UpdateFlowsBulk upates the bulk flow
1796func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301797 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001798}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001799
1800//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001801func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1802 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301803 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001804 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301805 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001806
khenaidoodc2116e2021-10-19 17:33:19 -04001807 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001808 ParentId: dh.device.Id,
1809 OnuId: onuID,
1810 ParentPortNo: parentPort,
1811 })
1812
Girish Gowdru0c588b22019-04-23 23:24:56 -04001813 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001814 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001815 "intf-id": parentPort,
1816 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001817 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001818 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 -08001819 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301820}
1821
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001822// SendPacketInToCore sends packet-in to core
1823// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1824// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001825func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001826 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001827 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001828 "port": logicalPort,
1829 "packet": hex.EncodeToString(packetPayload),
1830 "device-id": dh.device.Id,
1831 })
1832 }
khenaidoo106c61a2021-08-11 18:05:46 -04001833
khenaidoodc2116e2021-10-19 17:33:19 -04001834 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001835 DeviceId: dh.device.Id,
1836 Port: logicalPort,
1837 Packet: packetPayload,
1838 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301839 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001840 "source": "adapter",
1841 "destination": "core",
1842 "device-id": dh.device.Id,
1843 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001844 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001845 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001846 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001847 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001848 "packet": hex.EncodeToString(packetPayload),
1849 "device-id": dh.device.Id,
1850 })
1851 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001852 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001853}
1854
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001855// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001856func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001857 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001858
1859 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1860 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001861 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001862 }
1863
Kent Hagermane6ff1012020-07-14 15:07:53 -04001864 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001865 metrics := dh.metrics.GetSubscriberMetrics()
1866 for _, m := range pmConfigs.Metrics {
1867 metrics[m.Name].Enabled = m.Enabled
1868
1869 }
1870 }
1871}
1872
khenaidoodc2116e2021-10-19 17:33:19 -04001873func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001874 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001875 var errorsList []error
1876
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001877 if dh.getDeviceDeletionInProgressFlag() {
1878 // The device itself is going to be reset as part of deletion. So nothing to be done.
1879 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1880 return nil
1881 }
1882
Girish Gowdru0c588b22019-04-23 23:24:56 -04001883 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001884 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001885 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001886
Neha Sharma96b7bf22020-06-15 10:37:32 +00001887 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301888 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001889 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301890 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001891 if flow_utils.HasGroup(flow) {
1892 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1893 } else {
yasin saplid0566272021-12-21 09:10:30 +00001894 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
Girish Gowdra491a9c62021-01-06 16:43:07 -08001895 }
Girish Gowdracefae192020-03-19 18:14:10 -07001896 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01001897 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
1898 //The flow we want to remove is not there, there is no need to throw an error
1899 logger.Warnw(ctx, "flow-to-remove-not-found",
1900 log.Fields{
1901 "ponIf": intfID,
1902 "flowToRemove": flow,
1903 "error": err,
1904 })
1905 } else {
1906 errorsList = append(errorsList, err)
1907 }
Girish Gowdracefae192020-03-19 18:14:10 -07001908 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001909 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301910
1911 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00001912 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001913 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301914 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001915 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301916 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001917 if flow_utils.HasGroup(flow) {
1918 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1919 } else {
yasin saplid0566272021-12-21 09:10:30 +00001920 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001921 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1922 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1923 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1924 } else {
yasin saplid0566272021-12-21 09:10:30 +00001925 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001926 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001927 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001928 if err != nil {
1929 errorsList = append(errorsList, err)
1930 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301931 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001932 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001933
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001934 return errorsList
1935}
1936
1937func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1938 var err error
1939 var errorsList []error
1940
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001941 if dh.getDeviceDeletionInProgressFlag() {
1942 // The device itself is going to be reset as part of deletion. So nothing to be done.
1943 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1944 return nil
1945 }
1946
Girish Gowdracefae192020-03-19 18:14:10 -07001947 // 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 +00001948 if groups != nil {
1949 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001950 // err = dh.groupMgr.AddGroup(ctx, group)
1951 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001952 if err != nil {
1953 errorsList = append(errorsList, err)
1954 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001955 }
1956 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001957 // err = dh.groupMgr.ModifyGroup(ctx, group)
1958 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001959 if err != nil {
1960 errorsList = append(errorsList, err)
1961 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001962 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001963 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001964 // err = dh.groupMgr.DeleteGroup(ctx, group)
1965 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001966 if err != nil {
1967 errorsList = append(errorsList, err)
1968 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001969 }
1970 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001971
1972 return errorsList
1973}
1974
1975//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001976func (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 -07001977
1978 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001979
1980 if dh.getDeviceDeletionInProgressFlag() {
1981 // The device itself is going to be reset as part of deletion. So nothing to be done.
1982 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1983 return nil
1984 }
1985
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001986 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1987 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1988 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001989 if len(errorsList) > 0 {
1990 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1991 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001992 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001993 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301994}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001995
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001996//DisableDevice disables the given device
1997//It marks the following for the given device:
1998//Device-Handler Admin-State : down
1999//Device Port-State: UNKNOWN
2000//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002001func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002002 /* On device disable ,admin state update has to be done prior sending request to agent since
2003 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002004 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002005 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002006 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002007 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002008 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002009 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002010 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002011 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002012 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002013 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302014
2015 dh.discOnus = sync.Map{}
2016 dh.onus = sync.Map{}
2017
Thomas Lee S85f37312020-04-03 17:06:12 +05302018 //stopping the stats collector
2019 dh.stopCollector <- true
2020
Neha Sharma96b7bf22020-06-15 10:37:32 +00002021 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002022 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05302023 //Update device Admin state
2024 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002025
kdarapu1afeceb2020-02-12 01:38:09 -05002026 // 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 -04002027 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002028 DeviceId: cloned.Id,
2029 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2030 OperStatus: voltha.OperStatus_UNKNOWN,
2031 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002032 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002033 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002034 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002035 return nil
2036}
2037
Neha Sharma96b7bf22020-06-15 10:37:32 +00002038func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002039 // Update onu state as unreachable in onu adapter
2040 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302041 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002042
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002043 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002044 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002045 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002046 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 -04002047 }
2048 if onuDevices != nil {
2049 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002050 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002051 DeviceId: onuDevice.Id,
2052 OnuIndication: &onuInd,
2053 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002054 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002055 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002056 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002057 }
2058
2059 }
2060 }
2061
2062}
2063
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002064//ReenableDevice re-enables the olt device after disable
2065//It marks the following for the given device:
2066//Device-Handler Admin-State : up
2067//Device Port-State: ACTIVE
2068//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002069func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002070 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302071 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002072 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302073 }
2074 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002075 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002076
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002077 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002078 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002079 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002080 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002081 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2082 } else {
2083 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2084 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2085 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002086 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002087 if retError == nil {
2088 //Update the device oper status as ACTIVE
2089 device.OperStatus = voltha.OperStatus_ACTIVE
2090 } else {
2091 //Update the device oper status as FAILED
2092 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002093 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002094 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002095
khenaidoodc2116e2021-10-19 17:33:19 -04002096 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002097 DeviceId: device.Id,
2098 OperStatus: device.OperStatus,
2099 ConnStatus: device.ConnectStatus,
2100 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302101 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002102 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002103 "connect-status": device.ConnectStatus,
2104 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002105 }
kesavand39e0aa32020-01-28 20:58:50 -05002106
Neha Sharma96b7bf22020-06-15 10:37:32 +00002107 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002108
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002109 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002110}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002111
npujarec5762e2020-01-01 14:08:48 +05302112func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002113 var uniID uint32
2114 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302115 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002116 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002117 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002118 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002119 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002120 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002121 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002122 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002123 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002124 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002125 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002126 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00002127 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002128 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002129 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002130 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00002131 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002132 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302133 }
yasin saplibddc2d72022-02-08 13:10:17 +00002134 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2135 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002136 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302137 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002138 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002139 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002140 logger.Debugw(ctx, "failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002141 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002142 }
2143 return nil
2144}
2145
Devmalya Paul495b94a2019-08-27 19:42:00 -04002146// 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 +05302147func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002148 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002149 /* Clear the KV store data associated with the all the UNI ports
2150 This clears up flow data and also resource map data for various
2151 other pon resources like alloc_id and gemport_id
2152 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002153
2154 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002155 var wg sync.WaitGroup
2156 wg.Add(1) // for the mcast routine below to finish
2157 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2158 for _, flMgr := range dh.flowMgr {
2159 wg.Add(1) // for the flow handler routine below to finish
2160 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2161 }
2162 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2163 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2164 } else {
2165 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2166 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002167
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002168 dh.cleanupDeviceResources(ctx)
2169 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002170 // Stop the Stats collector
2171 dh.stopCollector <- true
2172 // stop the heartbeat check routine
2173 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05302174 dh.lockDevice.RLock()
2175 // Stop the read indication only if it the routine is active
2176 if dh.isReadIndicationRoutineActive {
2177 dh.stopIndications <- true
2178 }
2179 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002180 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002181 //Reset the state
2182 if dh.Client != nil {
2183 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302184 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002185 }
2186 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002187 // There is no need to update the core about operation status and connection status of the OLT.
2188 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2189 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2190 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002191
khenaidoo7eb2d672021-10-22 19:08:50 -04002192 // Stop the adapter grpc clients for that parent device
2193 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002194 return nil
2195}
Kent Hagermane6ff1012020-07-14 15:07:53 -04002196func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002197
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002198 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302199 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002200 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002201 var err error
yasin sapli9e4c5092022-02-01 13:52:33 +00002202 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002203 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002204 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002205 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002206 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302207 }
2208 }
yasin saplibddc2d72022-02-08 13:10:17 +00002209 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx)
2210 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002211 dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002212 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2213 logger.Debug(ctx, err)
2214 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002215 }
yasin saplibddc2d72022-02-08 13:10:17 +00002216 // Clean up NNI manager's data
2217 _ = dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002218 }
A R Karthick1f85b802019-10-11 05:06:05 +00002219
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002220 // Take one final sweep at cleaning up KV store for the OLT device
2221 // Clean everything at <base-path-prefix>/openolt/<device-id>
2222 kvClient, err := kvstore.NewEtcdClient(ctx, dh.openOLT.KVStoreAddress, rsrcMgr.KvstoreTimeout, log.FatalLevel)
2223 if err == nil {
2224 kvBackend := &db.Backend{
2225 Client: kvClient,
2226 StoreType: dh.openOLT.KVStoreType,
2227 Address: dh.openOLT.KVStoreAddress,
2228 Timeout: rsrcMgr.KvstoreTimeout,
2229 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, dh.cm.Backend.PathPrefix, dh.device.Id)}
2230 _ = kvBackend.DeleteWithPrefix(ctx, "")
2231 }
2232
Devmalya Paul495b94a2019-08-27 19:42:00 -04002233 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302234 dh.onus.Range(func(key interface{}, value interface{}) bool {
2235 dh.onus.Delete(key)
2236 return true
2237 })
2238
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002239 /*Delete discovered ONU map for the device*/
2240 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2241 dh.discOnus.Delete(key)
2242 return true
2243 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002244}
2245
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002246//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002247func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002248 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302249 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002250 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002251 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002252 return nil
2253}
2254
David K. Bainbridge794735f2020-02-11 21:01:37 -08002255func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002256 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002257 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002258 "packet-indication": *packetIn,
2259 "device-id": dh.device.Id,
2260 "packet": hex.EncodeToString(packetIn.Pkt),
2261 })
2262 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002263 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002264 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002265 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002266 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002267 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002268 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002269 "logical-port-num": logicalPortNum,
2270 "device-id": dh.device.Id,
2271 "packet": hex.EncodeToString(packetIn.Pkt),
2272 })
2273 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274
khenaidoodc2116e2021-10-19 17:33:19 -04002275 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002276 DeviceId: dh.device.Id,
2277 Port: logicalPortNum,
2278 Packet: packetIn.Pkt,
2279 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302280 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002281 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302282 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002283 "device-id": dh.device.Id,
2284 "packet": hex.EncodeToString(packetIn.Pkt),
2285 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002286 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002287
Matteo Scandolo92186242020-06-12 10:54:18 -07002288 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002289 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002290 "packet": hex.EncodeToString(packetIn.Pkt),
2291 "device-id": dh.device.Id,
2292 })
2293 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002294 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002295}
2296
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002297// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002298func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002299 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002300 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002301 "device-id": dh.device.Id,
2302 "egress-port-no": egressPortNo,
2303 "pkt-length": len(packet.Data),
2304 "packet": hex.EncodeToString(packet.Data),
2305 })
2306 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002307
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002308 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002309 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002310 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2311 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302312 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2313 // Do not packet-out lldp packets on uni port.
2314 // ONOS has no clue about uni/nni ports, it just packets out on all
2315 // available ports on the Logical Switch. It should not be interested
2316 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002317 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002318 "device-id": dh.device.Id,
2319 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302320 return nil
2321 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002322 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2323 if innerEthType == 0x8100 {
2324 // q-in-q 802.1ad or 802.1q double tagged packet.
2325 // slice out the outer tag.
2326 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002327 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002328 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002329 "packet-data": hex.EncodeToString(packet.Data),
2330 "device-id": dh.device.Id,
2331 })
2332 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002333 }
2334 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002335 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2336 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2337 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002338
Girish Gowdra9602eb42020-09-09 15:50:39 -07002339 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002340 if err != nil {
2341 // In this case the openolt agent will receive the gemPortID as 0.
2342 // The agent tries to retrieve the gemPortID in this case.
2343 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002344 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002345 "intf-id": intfID,
2346 "onu-id": onuID,
2347 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002348 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302349 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002350 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002351 }
2352
2353 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002354 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002355 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002356 "egress-port-no": egressPortNo,
2357 "intf-id": intfID,
2358 "onu-id": onuID,
2359 "uni-id": uniID,
2360 "gem-port-id": gemPortID,
2361 "packet": hex.EncodeToString(packet.Data),
2362 "device-id": dh.device.Id,
2363 })
2364 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002365
npujarec5762e2020-01-01 14:08:48 +05302366 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302367 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002368 "source": "adapter",
2369 "destination": "onu",
2370 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002371 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002372 "oni-id": onuID,
2373 "uni-id": uniID,
2374 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002375 "packet": hex.EncodeToString(packet.Data),
2376 "device-id": dh.device.Id,
2377 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002378 }
2379 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002380 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002381 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002382 return olterrors.NewErrInvalidValue(log.Fields{
2383 "egress-nni-port": egressPortNo,
2384 "device-id": dh.device.Id,
2385 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002386 }
2387 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002388
Matteo Scandolo92186242020-06-12 10:54:18 -07002389 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002390 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002391 "uplink-pkt": uplinkPkt,
2392 "packet": hex.EncodeToString(packet.Data),
2393 "device-id": dh.device.Id,
2394 })
2395 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002396
npujarec5762e2020-01-01 14:08:48 +05302397 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002398 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2399 "packet": hex.EncodeToString(packet.Data),
2400 "device-id": dh.device.Id,
2401 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002402 }
2403 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002404 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302405 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002406 "egressPortType": egressPortType,
2407 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302408 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002409 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002410 }
2411 return nil
2412}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002413
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002414func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2415 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002416}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302417
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002418func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002419
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302420 // start the heartbeat check towards the OLT.
2421 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302422 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302423
2424 for {
2425 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2426 select {
2427 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002428 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002429 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002430 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302431 if timerCheck == nil {
2432 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002433 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302434 }
2435 } else {
2436 if timerCheck != nil {
2437 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002438 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302439 }
2440 timerCheck = nil
2441 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302442 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2443 if dh.heartbeatSignature == 0 {
2444 // First time the signature will be 0, update the signture to DB when not found.
2445 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2446 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2447 }
2448 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2449
2450 dh.lockDevice.RLock()
2451 // Stop the read indication only if it the routine is active
2452 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2453 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2454 // on next execution of the readIndication routine.
2455 if !dh.isReadIndicationRoutineActive {
2456 // Start reading indications
2457 go func() {
2458 if err = dh.readIndications(ctx); err != nil {
2459 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2460 }
2461 }()
2462 }
2463 dh.lockDevice.RUnlock()
2464
2465 } else {
2466 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2467 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2468 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2469 go dh.updateStateRebooted(ctx)
2470 }
2471
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302472 }
2473 cancel()
2474 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002475 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302476 return
2477 }
2478 }
2479}
2480
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002481func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002482 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002483 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002484 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2485 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2486 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2487 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2488 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002489 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002490 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2491 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002492 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302493
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302494 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002495 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002496 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002497 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002498 DeviceId: dh.device.Id,
2499 OperStatus: voltha.OperStatus_UNKNOWN,
2500 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2501 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002502 _ = 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 -04002503 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302504 /*
2505 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2506 DeviceId: dh.device.Id,
2507 PortTypeFilter: 0,
2508 OperStatus: voltha.OperStatus_UNKNOWN,
2509 }); err != nil {
2510 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2511 }
2512 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002513
2514 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002515 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002516 cloned := proto.Clone(device).(*voltha.Device)
2517 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2518 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2519 dh.device = cloned // update local copy of the device
2520 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002521
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002522 // Stop the Stats collector
2523 dh.stopCollector <- true
2524 // stop the heartbeat check routine
2525 dh.stopHeartbeatCheck <- true
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002526 dh.lockDevice.RLock()
2527 // Stop the read indication only if it the routine is active
2528 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2529 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2530 // on next execution of the readIndication routine.
2531 if dh.isReadIndicationRoutineActive {
2532 dh.stopIndications <- true
2533 }
2534 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002535 dh.transitionMap.Handle(ctx, DeviceInit)
2536
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302537 }
2538}
kesavand39e0aa32020-01-28 20:58:50 -05002539
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302540func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2541 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2542 if err != nil || device == nil {
2543 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2544 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2545 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2546 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2547 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2548 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2549 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2550 return
2551 }
2552
2553 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2554 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2555 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2556 DeviceId: dh.device.Id,
2557 OperStatus: voltha.OperStatus_REBOOTED,
2558 ConnStatus: voltha.ConnectStatus_REACHABLE,
2559 }); err != nil {
2560 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2561 }
2562
2563 dh.lockDevice.RLock()
2564 // Stop the read indication only if it the routine is active
2565 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2566 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2567 // on next execution of the readIndication routine.
2568 if dh.isReadIndicationRoutineActive {
2569 dh.stopIndications <- true
2570 }
2571 dh.lockDevice.RUnlock()
2572
2573 //raise olt communication failure event
2574 raisedTs := time.Now().Unix()
2575 cloned := proto.Clone(device).(*voltha.Device)
2576 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2577 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2578 dh.device = cloned // update local copy of the device
2579 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2580
2581 dh.cleanupDeviceResources(ctx)
2582 // Stop the Stats collector
2583 dh.stopCollector <- true
2584 // stop the heartbeat check routine
2585 dh.stopHeartbeatCheck <- true
2586
2587 var wg sync.WaitGroup
2588 wg.Add(1) // for the multicast handler routine
2589 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2590 for _, flMgr := range dh.flowMgr {
2591 wg.Add(1) // for the flow handler routine
2592 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2593 }
2594 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2595 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2596 } else {
2597 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2598 }
2599
2600 //reset adapter reconcile flag
2601 dh.adapterPreviouslyConnected = false
2602 for {
2603
2604 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2605 if err != nil || childDevices == nil {
2606 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2607 continue
2608 }
2609 if len(childDevices.Items) == 0 {
2610 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
2611 break
2612 } else {
2613 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
2614 time.Sleep(5 * time.Second)
2615 }
2616
2617 }
2618 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
2619 dh.transitionMap.Handle(ctx, DeviceInit)
2620
2621}
2622
kesavand39e0aa32020-01-28 20:58:50 -05002623// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002624func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2625 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2626 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002627}
2628
2629// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002630func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2631 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2632 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002633}
2634
kdarapu1afeceb2020-02-12 01:38:09 -05002635//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 +00002636func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2637 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002638 if port.GetType() == voltha.Port_ETHERNET_NNI {
2639 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002640 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302641 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302642 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002643 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002644 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002645 }
2646 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002647 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002648 ponIntf := &oop.Interface{IntfId: ponID}
2649 var operStatus voltha.OperStatus_Types
2650 if enablePort {
2651 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302652 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002653
2654 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302655 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002656 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002657 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002658 }
2659 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002660 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002661 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002662 } else {
2663 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302664 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002665 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302666 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002667 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002668 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002669 }
2670 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002671 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002672 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002673 }
khenaidoodc2116e2021-10-19 17:33:19 -04002674 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002675 DeviceId: dh.device.Id,
2676 PortType: voltha.Port_PON_OLT,
2677 PortNo: port.PortNo,
2678 OperStatus: operStatus,
2679 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302680 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302681 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002682 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002683 }
2684 return nil
2685}
2686
kdarapu1afeceb2020-02-12 01:38:09 -05002687//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002688func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002689 // Disable the port and update the oper_port_status to core
2690 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002691 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002692 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002693 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302694 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302695 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002696 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002697 }
2698 }
2699 }
2700 return nil
2701}
2702
2703//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002704func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2705 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2706 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002707 if port.Type == voltha.Port_ETHERNET_NNI {
2708 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002709 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002710 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002711 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002712 }
2713 }
2714 if port.Type == voltha.Port_PON_OLT {
2715 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002716 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002717 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002718 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002719 }
2720 }
2721 }
2722}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002723
2724// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002725func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002726 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07002727 if dh.getDeviceDeletionInProgressFlag() {
2728 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
2729 // will reboot, so everything will be reset on the pOLT too.
2730 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
2731 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
2732 return nil
2733 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002734 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002735 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002736
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002737 var sn *oop.SerialNumber
2738 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002739 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302740 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002741 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302742 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002743 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002744 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002745
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002746 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002747 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00002748 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002749 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2750 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2751 "device-id": dh.device.Id,
2752 "intf-id": intfID,
2753 "onuID": onuID,
2754 "err": err})
2755 } else {
2756 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00002757 // Delete flows from device before schedulers and queue
2758 // Clear flowids for gem cache.
2759 removedFlows := []uint64{}
2760 for _, gem := range onuGem.GemPorts {
2761 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
2762 for _, flowID := range flowIDs {
2763 //multiple gem port can have the same flow id
2764 //it is better to send only one flowRemove request to the agent
2765 var alreadyRemoved bool
2766 for _, removedFlowID := range removedFlows {
2767 if removedFlowID == flowID {
2768 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
2769 alreadyRemoved = true
2770 break
2771 }
2772 }
2773 if !alreadyRemoved {
2774 flow := &oop.Flow{FlowId: flowID}
2775 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
2776 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
2777 "device-id": dh.device.Id,
2778 "onu-device": onu,
2779 "err": err})
2780 }
2781 removedFlows = appendUnique64bit(removedFlows, flowID)
2782 }
2783 }
2784 }
2785 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
2786 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002787 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2788 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2789 "device-id": dh.device.Id,
2790 "onu-device": onu,
2791 "err": err})
2792 }
yasin saplibddc2d72022-02-08 13:10:17 +00002793 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002794 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2795 "intf-id": intfID,
2796 "onu-device": onu,
2797 "onu-gem": onuGem,
2798 "err": err})
2799 //Not returning error on cleanup.
2800 }
2801 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302802
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002803 }
yasin saplibddc2d72022-02-08 13:10:17 +00002804 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002805 dh.onus.Delete(onuKey)
2806 dh.discOnus.Delete(onuSn)
2807
2808 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002809 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302810 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302811 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002812 "onu-id": onuID}, err).Log()
2813 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002814
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002815 return nil
2816}
Girish Gowdracefae192020-03-19 18:14:10 -07002817
2818func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002819 for _, field := range flow_utils.GetOfbFields(flow) {
2820 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002821 return field.GetPort()
2822 }
2823 }
2824 return InvalidPort
2825}
2826
2827func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002828 for _, action := range flow_utils.GetActions(flow) {
2829 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002830 if out := action.GetOutput(); out != nil {
2831 return out.GetPort()
2832 }
2833 }
2834 }
2835 return InvalidPort
2836}
2837
Girish Gowdracefae192020-03-19 18:14:10 -07002838func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2839 inPort := getInPortFromFlow(flow)
2840 outPort := getOutPortFromFlow(flow)
2841
2842 if inPort == InvalidPort || outPort == InvalidPort {
2843 return inPort, outPort
2844 }
2845
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002846 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002847 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002848 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002849 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002850 return uniPort, outPort
2851 }
2852 }
2853 } else {
2854 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002855 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002856 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002857 return inPort, uniPort
2858 }
2859 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002860 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002861 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002862 return uniPort, outPort
2863 }
2864 }
2865 }
2866
2867 return InvalidPort, InvalidPort
2868}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002869
2870func extractOmciTransactionID(omciPkt []byte) uint16 {
2871 if len(omciPkt) > 3 {
2872 d := omciPkt[0:2]
2873 transid := binary.BigEndian.Uint16(d)
2874 return transid
2875 }
2876 return 0
2877}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002878
2879// StoreOnuDevice stores the onu parameters to the local cache.
2880func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2881 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2882 dh.onus.Store(onuKey, onuDevice)
2883}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002884
khenaidoodc2116e2021-10-19 17:33:19 -04002885func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002886 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002887 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002888 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002889 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002890 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002891 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002892 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002893 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2894 return nil, err
2895 }
2896 ID = device.ProxyAddress.GetOnuId()
2897 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2898 valueparam.Onu = &Onu
2899 valueparam.Value = value
2900
2901 // This API is unsupported until agent patch is added
2902 resp.Unsupported = uint32(value)
2903 _ = ctx
2904
2905 // Uncomment this code once agent changes are complete and tests
2906 /*
2907 resp, err = dh.Client.GetValue(ctx, valueparam)
2908 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002909 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002910 return nil, err
2911 }
2912 */
2913
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002914 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 -08002915 return resp, nil
2916}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002917
yasin saplid0566272021-12-21 09:10:30 +00002918func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
2919 // Default to NNI
2920 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07002921 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002922 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002923 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002924 }
2925 return intfID
2926}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002927
Mahir Gunyelb0046752021-02-26 13:51:05 -08002928func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2929 dh.perPonOnuIndicationChannelLock.Lock()
2930 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2931 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002932 return ch.indicationChannel
2933 }
2934 channels := onuIndicationChannels{
2935 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002936 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002937 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002938 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002939 stopChannel: make(chan struct{}),
2940 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002941 dh.perPonOnuIndicationChannel[intfID] = channels
2942 dh.perPonOnuIndicationChannelLock.Unlock()
2943 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002944 return channels.indicationChannel
2945
2946}
2947
Mahir Gunyelb0046752021-02-26 13:51:05 -08002948func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2949 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2950 dh.perPonOnuIndicationChannelLock.Lock()
2951 defer dh.perPonOnuIndicationChannelLock.Unlock()
2952 for _, v := range dh.perPonOnuIndicationChannel {
2953 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002954 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002955 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002956}
2957
Mahir Gunyelb0046752021-02-26 13:51:05 -08002958func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2959 ind := onuIndicationMsg{
2960 ctx: ctx,
2961 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002962 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002963 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002964 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002965 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002966}
2967
Mahir Gunyelb0046752021-02-26 13:51:05 -08002968func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002969 for {
2970 select {
2971 // process one indication per onu, before proceeding to the next one
2972 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08002973 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002974 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08002975 "ind": indication})
2976 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002977 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002978 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002979 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2980 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002981 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002982 }
2983 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002984 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002985 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2986 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002987 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002988 }
2989 }
2990 case <-onuChannels.stopChannel:
2991 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2992 close(onuChannels.indicationChannel)
2993 return
2994 }
2995 }
2996}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002997
2998// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2999// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003000func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003001 if dh.getDeviceDeletionInProgressFlag() {
3002 // The device itself is going to be reset as part of deletion. So nothing to be done.
3003 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3004 return nil
3005 }
3006
Girish Gowdra491a9c62021-01-06 16:43:07 -08003007 // Step1 : Fill McastFlowOrGroupControlBlock
3008 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3009 // Step3 : Wait on response channel for response
3010 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003011 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003012 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3013 errChan := make(chan error)
3014 var groupID uint32
3015 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3016 ctx: ctx,
3017 flowOrGroupAction: action,
3018 flow: flow,
3019 group: group,
3020 errChan: &errChan,
3021 }
3022 if flow != nil {
3023 groupID = flow_utils.GetGroup(flow)
3024 } else if group != nil {
3025 groupID = group.Desc.GroupId
3026 } else {
3027 return errors.New("flow-and-group-both-nil")
3028 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003029 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3030 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3031 // Derive the appropriate go routine to handle the request by a simple module operation.
3032 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3033 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3034 // Wait for handler to return error value
3035 err := <-errChan
3036 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3037 return err
3038 }
3039 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3040 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003041}
3042
3043// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003044func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003045 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003046 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003047 // block on the channel to receive an incoming mcast flow/group
3048 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003049 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3050 if mcastFlowOrGroupCb.flow != nil {
3051 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3052 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3053 log.Fields{"device-id": dh.device.Id,
3054 "flowToAdd": mcastFlowOrGroupCb.flow})
3055 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
3056 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3057 // Pass the return value over the return channel
3058 *mcastFlowOrGroupCb.errChan <- err
3059 } else { // flow remove
3060 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3061 log.Fields{"device-id": dh.device.Id,
3062 "flowToRemove": mcastFlowOrGroupCb.flow})
3063 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
3064 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3065 // Pass the return value over the return channel
3066 *mcastFlowOrGroupCb.errChan <- err
3067 }
3068 } else { // mcast group
3069 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3070 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3071 log.Fields{"device-id": dh.device.Id,
3072 "groupToAdd": mcastFlowOrGroupCb.group})
3073 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3074 // Pass the return value over the return channel
3075 *mcastFlowOrGroupCb.errChan <- err
3076 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3077 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3078 log.Fields{"device-id": dh.device.Id,
3079 "groupToModify": mcastFlowOrGroupCb.group})
3080 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3081 // Pass the return value over the return channel
3082 *mcastFlowOrGroupCb.errChan <- err
3083 } else { // group remove
3084 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3085 log.Fields{"device-id": dh.device.Id,
3086 "groupToRemove": mcastFlowOrGroupCb.group})
3087 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3088 // Pass the return value over the return channel
3089 *mcastFlowOrGroupCb.errChan <- err
3090 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003091 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003092 case <-stopHandler:
3093 dh.mcastHandlerRoutineActive[routineIndex] = false
3094 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003095 }
3096 }
3097}
kesavand62126212021-01-12 04:56:06 -05003098
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003099// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003100func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003101 for i, v := range dh.stopMcastHandlerRoutine {
3102 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003103 select {
3104 case v <- true:
3105 case <-time.After(time.Second * 5):
3106 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3107 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003108 }
3109 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003110 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003111 logger.Debug(ctx, "stopped all mcast handler routines")
3112}
3113
kesavand62126212021-01-12 04:56:06 -05003114func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3115
3116 singleValResp := extension.SingleGetValueResponse{
3117 Response: &extension.GetValueResponse{
3118 Response: &extension.GetValueResponse_PortCoutners{
3119 PortCoutners: &extension.GetOltPortCountersResponse{},
3120 },
3121 },
3122 }
3123
3124 errResp := func(status extension.GetValueResponse_Status,
3125 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3126 return &extension.SingleGetValueResponse{
3127 Response: &extension.GetValueResponse{
3128 Status: status,
3129 ErrReason: reason,
3130 },
3131 }
3132 }
3133
3134 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3135 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3136 //send error response
3137 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3138 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3139 }
3140 statIndChn := make(chan bool, 1)
3141 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3142 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3143 //request openOlt agent to send the the port statistics indication
3144
3145 go func() {
3146 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3147 if err != nil {
3148 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3149 }
3150 }()
3151 select {
3152 case <-statIndChn:
3153 //indication received for ports stats
3154 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3155 case <-time.After(oltPortInfoTimeout * time.Second):
3156 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3157 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3158 case <-ctx.Done():
3159 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3160 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3161 }
3162 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3163 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003164 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003165 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3166 cmnni := dh.portStats.collectNNIMetrics(intfID)
3167 if cmnni == nil {
3168 //TODO define the error reason
3169 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3170 }
3171 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3172 return &singleValResp
3173
3174 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3175 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003176 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003177 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3178 cmpon := dh.portStats.collectPONMetrics(intfID)
3179 if cmpon == nil {
3180 //TODO define the error reason
3181 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3182 }
3183 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3184 return &singleValResp
3185 }
3186 }
3187 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3188}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303189
3190func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3191
3192 singleValResp := extension.SingleGetValueResponse{
3193 Response: &extension.GetValueResponse{
3194 Response: &extension.GetValueResponse_OnuPonCounters{
3195 OnuPonCounters: &extension.GetOnuCountersResponse{},
3196 },
3197 },
3198 }
3199
3200 errResp := func(status extension.GetValueResponse_Status,
3201 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3202 return &extension.SingleGetValueResponse{
3203 Response: &extension.GetValueResponse{
3204 Status: status,
3205 ErrReason: reason,
3206 },
3207 }
3208 }
3209 intfID := onuPonInfo.IntfId
3210 onuID := onuPonInfo.OnuId
3211 onuKey := dh.formOnuKey(intfID, onuID)
3212
3213 if _, ok := dh.onus.Load(onuKey); !ok {
3214 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3215 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3216 }
3217 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3218 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3219 if cmnni == nil {
3220 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3221 }
3222 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3223 return &singleValResp
3224
3225}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003226
3227func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3228
3229 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3230 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3231 if err != nil {
3232 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3233 return generateSingleGetValueErrorResponse(err)
3234 }
3235 return &extension.SingleGetValueResponse{
3236 Response: &extension.GetValueResponse{
3237 Status: extension.GetValueResponse_OK,
3238 Response: &extension.GetValueResponse_RxPower{
3239 RxPower: &extension.GetRxPowerResponse{
3240 IntfId: rxPowerRequest.IntfId,
3241 OnuId: rxPowerRequest.OnuId,
3242 Status: rxPower.Status,
3243 FailReason: rxPower.FailReason.String(),
3244 RxPower: rxPower.RxPowerMeanDbm,
3245 },
3246 },
3247 },
3248 }
3249}
3250
3251func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3252 errResp := func(status extension.GetValueResponse_Status,
3253 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3254 return &extension.SingleGetValueResponse{
3255 Response: &extension.GetValueResponse{
3256 Status: status,
3257 ErrReason: reason,
3258 },
3259 }
3260 }
3261
3262 if err != nil {
3263 if e, ok := status.FromError(err); ok {
3264 switch e.Code() {
3265 case codes.Internal:
3266 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3267 case codes.DeadlineExceeded:
3268 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3269 case codes.Unimplemented:
3270 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3271 case codes.NotFound:
3272 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3273 }
3274 }
3275 }
3276
3277 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3278}
khenaidoo106c61a2021-08-11 18:05:46 -04003279
3280/*
3281Helper functions to communicate with Core
3282*/
3283
3284func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3285 cClient, err := dh.coreClient.GetCoreServiceClient()
3286 if err != nil || cClient == nil {
3287 return nil, err
3288 }
3289 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3290 defer cancel()
3291 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3292}
3293
khenaidoodc2116e2021-10-19 17:33:19 -04003294func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003295 cClient, err := dh.coreClient.GetCoreServiceClient()
3296 if err != nil || cClient == nil {
3297 return nil, err
3298 }
3299 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3300 defer cancel()
3301 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3302}
3303
khenaidoodc2116e2021-10-19 17:33:19 -04003304func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003305 cClient, err := dh.coreClient.GetCoreServiceClient()
3306 if err != nil || cClient == nil {
3307 return err
3308 }
3309 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3310 defer cancel()
3311 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3312 return err
3313}
3314
3315func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3316 cClient, err := dh.coreClient.GetCoreServiceClient()
3317 if err != nil || cClient == nil {
3318 return nil, err
3319 }
3320 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3321 defer cancel()
3322 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3323}
3324
3325func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3326 cClient, err := dh.coreClient.GetCoreServiceClient()
3327 if err != nil || cClient == nil {
3328 return nil, err
3329 }
3330 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3331 defer cancel()
3332 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3333}
3334
3335func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3336 cClient, err := dh.coreClient.GetCoreServiceClient()
3337 if err != nil || cClient == nil {
3338 return err
3339 }
3340 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3341 defer cancel()
3342 _, err = cClient.DeviceUpdate(subCtx, device)
3343 return err
3344}
3345
khenaidoodc2116e2021-10-19 17:33:19 -04003346func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003347 cClient, err := dh.coreClient.GetCoreServiceClient()
3348 if err != nil || cClient == nil {
3349 return nil, err
3350 }
3351 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3352 defer cancel()
3353 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3354}
3355
khenaidoodc2116e2021-10-19 17:33:19 -04003356func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003357 cClient, err := dh.coreClient.GetCoreServiceClient()
3358 if err != nil || cClient == nil {
3359 return err
3360 }
3361 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3362 defer cancel()
3363 _, err = cClient.SendPacketIn(subCtx, pkt)
3364 return err
3365}
3366
3367func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3368 cClient, err := dh.coreClient.GetCoreServiceClient()
3369 if err != nil || cClient == nil {
3370 return err
3371 }
3372 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3373 defer cancel()
3374 _, err = cClient.PortCreated(subCtx, port)
3375 return err
3376}
3377
khenaidoodc2116e2021-10-19 17:33:19 -04003378func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003379 cClient, err := dh.coreClient.GetCoreServiceClient()
3380 if err != nil || cClient == nil {
3381 return err
3382 }
3383 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3384 defer cancel()
3385 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3386 return err
3387}
3388
khenaidoodc2116e2021-10-19 17:33:19 -04003389func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003390 cClient, err := dh.coreClient.GetCoreServiceClient()
3391 if err != nil || cClient == nil {
3392 return err
3393 }
3394 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3395 defer cancel()
3396 _, err = cClient.PortStateUpdate(subCtx, portState)
3397 return err
3398}
3399
khenaidoodc2116e2021-10-19 17:33:19 -04003400func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003401 cClient, err := dh.coreClient.GetCoreServiceClient()
3402 if err != nil || cClient == nil {
3403 return nil, err
3404 }
3405 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3406 defer cancel()
3407 return cClient.GetDevicePort(subCtx, portFilter)
3408}
3409
3410/*
3411Helper functions to communicate with child adapter
3412*/
3413
khenaidoodc2116e2021-10-19 17:33:19 -04003414func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003415 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3416 if err != nil || aClient == nil {
3417 return err
3418 }
3419 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3420 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3421 defer cancel()
3422 _, err = aClient.OmciIndication(subCtx, response)
3423 return err
3424}
3425
khenaidoodc2116e2021-10-19 17:33:19 -04003426func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003427 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3428 if err != nil || aClient == nil {
3429 return err
3430 }
3431 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3432 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3433 defer cancel()
3434 _, err = aClient.OnuIndication(subCtx, onuInd)
3435 return err
3436}
3437
khenaidoodc2116e2021-10-19 17:33:19 -04003438func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003439 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3440 if err != nil || aClient == nil {
3441 return err
3442 }
3443 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3444 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3445 defer cancel()
3446 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3447 return err
3448}
3449
khenaidoodc2116e2021-10-19 17:33:19 -04003450func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003451 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3452 if err != nil || aClient == nil {
3453 return err
3454 }
3455 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3456 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3457 defer cancel()
3458 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3459 return err
3460}
3461
khenaidoodc2116e2021-10-19 17:33:19 -04003462func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003463 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3464 if err != nil || aClient == nil {
3465 return err
3466 }
3467 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3468 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3469 defer cancel()
3470 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3471 return err
3472}
3473
3474/*
3475Helper functions for remote communication
3476*/
3477
3478// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3479// supports is deleted
3480func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3481 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3482
3483 dh.lockChildAdapterClients.Lock()
3484 defer dh.lockChildAdapterClients.Unlock()
3485 if _, ok := dh.childAdapterClients[endpoint]; ok {
3486 // Already set
3487 return nil
3488 }
3489
3490 // Setup child's adapter grpc connection
3491 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003492 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3493 dh.cfg.AdapterEndpoint,
3494 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05003495 "onu_inter_adapter_service.OnuInterAdapterService",
3496 dh.onuInterAdapterRestarted,
3497 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003498 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3499 return err
3500 }
khenaidooefff76e2021-12-15 16:51:30 -05003501 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003502
3503 // Wait until we have a connection to the child adapter.
3504 // Unlimited retries or until context expires
3505 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3506 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3507 for {
3508 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3509 if err == nil && client != nil {
3510 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3511 break
3512 }
3513 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3514 // Backoff
3515 if err = backoff.Backoff(subCtx); err != nil {
3516 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3517 break
3518 }
3519 }
3520 return nil
3521}
3522
khenaidoodc2116e2021-10-19 17:33:19 -04003523func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003524
3525 // First check from cache
3526 dh.lockChildAdapterClients.RLock()
3527 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3528 dh.lockChildAdapterClients.RUnlock()
3529 return cgClient.GetOnuInterAdapterServiceClient()
3530 }
3531 dh.lockChildAdapterClients.RUnlock()
3532
3533 // Set the child connection - can occur on restarts
3534 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3535 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3536 cancel()
3537 if err != nil {
3538 return nil, err
3539 }
3540
3541 // Get the child client now
3542 dh.lockChildAdapterClients.RLock()
3543 defer dh.lockChildAdapterClients.RUnlock()
3544 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3545 return cgClient.GetOnuInterAdapterServiceClient()
3546 }
3547 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3548}
3549
3550func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3551 dh.lockChildAdapterClients.Lock()
3552 defer dh.lockChildAdapterClients.Unlock()
3553 for key, client := range dh.childAdapterClients {
3554 client.Stop(ctx)
3555 delete(dh.childAdapterClients, key)
3556 }
3557}
3558
khenaidooefff76e2021-12-15 16:51:30 -05003559// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
3560func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
3561 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003562 return nil
3563}
3564
khenaidooefff76e2021-12-15 16:51:30 -05003565// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
3566func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
3567 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003568 return nil
3569 }
khenaidooefff76e2021-12-15 16:51:30 -05003570 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04003571}
Girish Gowdra950326e2021-11-05 12:43:24 -07003572
3573func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3574 dh.lockDevice.Lock()
3575 defer dh.lockDevice.Unlock()
3576 dh.isDeviceDeletionInProgress = flag
3577}
3578
3579func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3580 dh.lockDevice.RLock()
3581 defer dh.lockDevice.RUnlock()
3582 return dh.isDeviceDeletionInProgress
3583}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003584
3585// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3586// Returns false if waiting timed out.
3587func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3588 c := make(chan struct{})
3589 go func() {
3590 defer close(c)
3591 wg.Wait()
3592 }()
3593 select {
3594 case <-c:
3595 return true // completed normally
3596 case <-time.After(timeout):
3597 return false // timed out
3598 }
3599}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303600
3601func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
3602 val, err := json.Marshal(signature)
3603 if err != nil {
3604 logger.Error(ctx, "failed-to-marshal")
3605 return
3606 }
3607 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
3608 logger.Error(ctx, "failed-to-store-hearbeat-signature")
3609 }
3610}
3611
3612func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
3613 var signature uint32
3614
3615 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
3616 if er == nil {
3617 if Value != nil {
3618 Val, er := kvstore.ToByte(Value.Value)
3619 if er != nil {
3620 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
3621 return signature
3622 }
3623 if er = json.Unmarshal(Val, &signature); er != nil {
3624 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
3625 return signature
3626 }
3627 }
3628 }
3629 return signature
3630}