blob: 37c5397a5d49a9a97cf53f6784be529a4245e7e7 [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
Mahir Gunyela2e68702022-12-07 00:00:42 -080017// Package core provides the utility for olt devices, flows and statistics
Scott Bakerdbd960e2020-02-28 08:57:51 -080018package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053024 "encoding/json"
Girish Gowdra491a9c62021-01-06 16:43:07 -080025 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "fmt"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
Elia Battiston599d25f2022-02-16 14:49:08 +010033 "github.com/opencord/voltha-lib-go/v7/pkg/db"
34 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
35
khenaidoo106c61a2021-08-11 18:05:46 -040036 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040037
Matteo Scandolo945e4012019-12-12 14:16:11 -080038 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070039 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000040 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
41 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040042 "github.com/opencord/voltha-lib-go/v7/pkg/config"
43 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
44 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
45 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070046 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040047 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080048
khenaidoo106c61a2021-08-11 18:05:46 -040049 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053050 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080051 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040052 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040053 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040054 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040055 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
56 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040057 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
58 oop "github.com/opencord/voltha-protos/v5/go/openolt"
59 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070060 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040061 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040062 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053063)
64
salmansiddiqui7ac62132019-08-22 03:58:50 +000065// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040066const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080067 InvalidPort = 0xffffffff
68 MaxNumOfGroupHandlerChannels = 256
69
70 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
71 McastFlowOrGroupModify = "McastFlowOrGroupModify"
72 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050073 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010074
75 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053076 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040077)
78
Mahir Gunyela2e68702022-12-07 00:00:42 -080079// DeviceHandler will interact with the OLT device.
Phaneendra Manda4c62c802019-03-06 21:37:49 +053080type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040081 cm *config.ConfigManager
82 device *voltha.Device
83 cfg *conf.AdapterFlags
84 coreClient *vgrpc.Client
85 childAdapterClients map[string]*vgrpc.Client
86 lockChildAdapterClients sync.RWMutex
87 EventProxy eventif.EventProxy
88 openOLT *OpenOLT
khenaidooefff76e2021-12-15 16:51:30 -050089 exitChannel chan struct{}
khenaidoo106c61a2021-08-11 18:05:46 -040090 lockDevice sync.RWMutex
91 Client oop.OpenoltClient
92 transitionMap *TransitionMap
93 clientCon *grpc.ClientConn
94 flowMgr []*OpenOltFlowMgr
95 groupMgr *OpenOltGroupMgr
96 eventMgr *OpenOltEventMgr
97 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053098 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070099
100 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530101
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700102 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
103 // if the value is true that means the OnuDiscovery indication
104 // is currently being processed and thus we can ignore concurrent requests
105 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
106 // if we do it means something went wrong and we need to retry
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700107 discOnus sync.Map
108 onus sync.Map
109 portStats *OpenOltStatisticsMgr
110 metrics *pmmetrics.PmMetrics
111 stopCollector chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000112 isCollectorActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700113 stopHeartbeatCheck chan bool
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000114 isHeartbeatCheckActive bool
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700115 activePorts sync.Map
116 stopIndications chan bool
117 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700118
Mahir Gunyelb0046752021-02-26 13:51:05 -0800119 totalPonPorts uint32
120 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
121 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800122
123 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
124 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700125 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
126 stopMcastHandlerRoutine []chan bool
127 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000128
129 adapterPreviouslyConnected bool
130 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700131
132 isDeviceDeletionInProgress bool
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530133 heartbeatSignature uint32
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134}
135
Mahir Gunyela2e68702022-12-07 00:00:42 -0800136// OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700137type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400138 deviceID string
139 deviceType string
140 serialNumber string
141 onuID uint32
142 intfID uint32
143 proxyDeviceID string
144 losRaised bool
145 rdiRaised bool
146 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700147}
148
Mahir Gunyelb0046752021-02-26 13:51:05 -0800149type onuIndicationMsg struct {
150 ctx context.Context
151 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800152}
153
154type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800155 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800156 stopChannel chan struct{}
157}
158
Mahir Gunyela2e68702022-12-07 00:00:42 -0800159// McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
160// The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
161// There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
162// and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800163type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400164 ctx context.Context // Flow/group handler context
165 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
166 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
167 group *of.OfpGroupEntry // Group message (can be nil or valid group)
168 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800169}
170
Naga Manjunath7615e552019-10-11 22:35:47 +0530171var pmNames = []string{
172 "rx_bytes",
173 "rx_packets",
174 "rx_mcast_packets",
175 "rx_bcast_packets",
176 "tx_bytes",
177 "tx_packets",
178 "tx_mcast_packets",
179 "tx_bcast_packets",
180}
181
Mahir Gunyela2e68702022-12-07 00:00:42 -0800182// NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400183func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700184 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700185 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700186 device.deviceType = deviceTp
187 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700188 device.onuID = onuID
189 device.intfID = intfID
190 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530191 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400192 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700193 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530194}
195
Mahir Gunyela2e68702022-12-07 00:00:42 -0800196// NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400197func NewDeviceHandler(cc *vgrpc.Client, ep eventif.EventProxy, device *voltha.Device, adapter *OpenOLT, cm *config.ConfigManager, cfg *conf.AdapterFlags) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700198 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530199 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800200 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400201 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400202 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700203 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700204 dh.device = cloned
205 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500206 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700207 dh.lockDevice = sync.RWMutex{}
Holger Hildebrandte6c877b2022-09-15 13:51:39 +0000208 dh.stopCollector = make(chan bool, 1) // TODO: Why buffered?
209 dh.stopHeartbeatCheck = make(chan bool, 1) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530210 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500211 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800212 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800213 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400214 dh.childAdapterClients = make(map[string]*vgrpc.Client)
215 dh.cfg = cfg
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530216 kvStoreDevicePath := fmt.Sprintf(dh.cm.Backend.PathPrefix, "/%s/", dh.device.Id)
217 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, kvStoreDevicePath)
218 if dh.kvStore == nil {
219 logger.Error(ctx, "Failed to setup KV store")
220 return nil
221 }
222
Girish Gowdra491a9c62021-01-06 16:43:07 -0800223 // Create a slice of buffered channels for handling concurrent mcast flow/group.
224 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700225 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
226 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800227 for i := range dh.incomingMcastFlowOrGroup {
228 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800229 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800230 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
231 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
232 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
233 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700234 dh.mcastHandlerRoutineActive[i] = true
235 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800236 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700237 //TODO initialize the support classes.
238 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530239}
240
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530241func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
242 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
243 switch storeType {
244 case "etcd":
245 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
246 }
247 return nil, errors.New("unsupported-kv-store")
248}
249
250// SetKVClient sets the KV client and return a kv backend
251func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
252 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
253 if err != nil {
254 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
255 return nil
256 }
257
258 kvbackend := &db.Backend{
259 Client: kvClient,
260 StoreType: backend,
261 Address: addr,
262 Timeout: rsrcMgr.KvstoreTimeout,
263 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
264
265 return kvbackend
266}
267
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530268// start save the device to the data model
269func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700270 dh.lockDevice.Lock()
271 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000272 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700273 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000274 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530275}
276
khenaidooefff76e2021-12-15 16:51:30 -0500277// Stop stops the device handler
278func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700279 dh.lockDevice.Lock()
280 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000281 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500282 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400283
khenaidooefff76e2021-12-15 16:51:30 -0500284 // Delete (which will stop also) all grpc connections to the child adapters
285 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000286 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530287}
288
ssiddiqui04386ee2021-08-23 21:58:25 +0530289func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
290 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
291 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
292 if pooledIntfID == intfID {
293 return resourceRanges.GetTechnology()
294 }
295 }
296 }
297 return ""
298}
299
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400300func macifyIP(ip net.IP) string {
301 if len(ip) > 0 {
302 oct1 := strconv.FormatInt(int64(ip[12]), 16)
303 oct2 := strconv.FormatInt(int64(ip[13]), 16)
304 oct3 := strconv.FormatInt(int64(ip[14]), 16)
305 oct4 := strconv.FormatInt(int64(ip[15]), 16)
306 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
307 }
308 return ""
309}
310
Neha Sharma96b7bf22020-06-15 10:37:32 +0000311func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400312 var genmac string
313 var addr net.IP
314 var ips []string
315 var err error
316
Neha Sharma96b7bf22020-06-15 10:37:32 +0000317 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400318
319 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000320 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400321
322 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000323 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400324 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000325 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400326 }
327 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530329 log.Fields{"host": ips[0],
330 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400331 return genmac, nil
332 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000333 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400334 }
335
336 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000337 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530338 log.Fields{"host": host,
339 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400340 return genmac, nil
341}
342
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530343func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700344 slist := strings.Split(mac, ":")
345 result := make([]uint32, len(slist))
346 var err error
347 var tmp int64
348 for index, val := range slist {
349 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
350 return []uint32{1, 2, 3, 4, 5, 6}
351 }
352 result[index] = uint32(tmp)
353 }
354 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530355}
356
Mahir Gunyela2e68702022-12-07 00:00:42 -0800357// 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 -0800358func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530359
David K. Bainbridge794735f2020-02-11 21:01:37 -0800360 switch portType {
361 case voltha.Port_ETHERNET_NNI:
362 return fmt.Sprintf("nni-%d", portNum), nil
363 case voltha.Port_PON_OLT:
364 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700365 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800366
Girish Kumarf26e4882020-03-05 06:49:10 +0000367 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530368}
369
Elia Battiston596406d2022-02-02 12:19:00 +0100370func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
371 if speedMbps == 0 {
372 //In case it was not set in the indication
373 //and no other value was provided
374 speedMbps = defaultPortSpeedMbps
375 }
376
377 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
378 switch speedMbps {
379 case 1000000:
380 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
381 case 100000:
382 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
383 case 40000:
384 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
385 case 10000:
386 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
387 case 1000:
388 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
389 case 100:
390 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
391 case 10:
392 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
393 }
394
395 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
396
397 port := &of.OfpPort{
398 HwAddr: macAddressToUint32Array(macAddress),
399 Config: 0,
400 State: uint32(of.OfpPortState_OFPPS_LIVE),
401 Curr: capacity,
402 Advertised: capacity,
403 Peer: capacity,
404 CurrSpeed: speedMbps * 1000, //kbps
405 MaxSpeed: speedMbps * 1000, //kbps
406 }
407
408 return port
409}
410
411func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000412 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700413 if state == "up" {
414 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500415 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500416 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700417 } else {
418 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500419 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700420 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700421 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400422 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800423 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000424 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400425 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500426
khenaidoo106c61a2021-08-11 18:05:46 -0400427 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400428 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400429 DeviceId: dh.device.Id,
430 Port: portNum,
431 })
432 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000433 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400434 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400435 DeviceId: dh.device.Id,
436 PortType: portType,
437 PortNo: portNum,
438 OperStatus: operStatus})
439 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400440 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
441 "device-id": dh.device.Id,
442 "port-type": portType,
443 "port-number": portNum,
444 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500445 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400446 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500447 }
khenaidoo106c61a2021-08-11 18:05:46 -0400448
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400449 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400450 port = &voltha.Port{
451 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700452 PortNo: portNum,
453 Label: label,
454 Type: portType,
455 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100456 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700457 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000458 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700459 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400460 err = dh.createPortInCore(ctx, port)
461 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000462 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800463 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000464 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400465 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000466 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530467 return nil
468}
469
Kent Hagermane6ff1012020-07-14 15:07:53 -0400470func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400471 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530472 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400473 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
474 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530475 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800476 dh.lockDevice.Lock()
477 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530478 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530479}
480
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700481// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530482// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800483func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000484 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700485 defer func() {
486 dh.lockDevice.Lock()
487 dh.isReadIndicationRoutineActive = false
488 dh.lockDevice.Unlock()
489 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700490 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700491 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700492 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700493 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400494
David Bainbridgef5879ca2019-12-13 21:17:54 +0000495 // Create an exponential backoff around re-enabling indications. The
496 // maximum elapsed time for the back off is set to 0 so that we will
497 // continue to retry. The max interval defaults to 1m, but is set
498 // here for code clarity
499 indicationBackoff := backoff.NewExponentialBackOff()
500 indicationBackoff.MaxElapsedTime = 0
501 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700502
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700503 dh.lockDevice.Lock()
504 dh.isReadIndicationRoutineActive = true
505 dh.lockDevice.Unlock()
506
Girish Gowdra3f974912020-03-23 20:35:18 -0700507Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700508 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400509 select {
510 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000511 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700512 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400513 default:
514 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100515
516 select {
517 case <-indications.Context().Done():
518 if err != nil {
519 logger.Warnw(ctx, "error-during-enable-indications",
520 log.Fields{"err": err,
521 "device-id": dh.device.Id})
522 }
523
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400524 // Use an exponential back off to prevent getting into a tight loop
525 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100526 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
527 "device-id": dh.device.Id,
528 "duration": duration,
529 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400530 if duration == backoff.Stop {
531 // If we reach a maximum then warn and reset the backoff
532 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100533 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530534 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530535 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400536 indicationBackoff.Reset()
537 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700538
539 // On failure process a backoff timer while watching for stopIndications
540 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700541 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700542 select {
543 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000544 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700545 if !backoffTimer.Stop() {
546 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700547 }
548 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700549 case <-backoffTimer.C:
550 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700551 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700552 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
553 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400554 }
555 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100556 default:
557 if err != nil {
558 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530559 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530560 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100561 // Close the stream, and re-initialize it
562 if err = indications.CloseSend(); err != nil {
563 // Ok to ignore here, because we landed here due to a problem on the stream
564 // In all probability, the closeSend call may fail
565 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
566 log.Fields{"err": err,
567 "device-id": dh.device.Id})
568 }
569 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
570 return err
571 }
572 // once we re-initialized the indication stream, continue to read indications
573 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700574 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100575 // Reset backoff if we have a successful receive
576 indicationBackoff.Reset()
577 // When OLT is admin down, ignore all indications.
578 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
579 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
580 log.Fields{"indication": indication,
581 "device-id": dh.device.Id})
582 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700583 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100584 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530585 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700586 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700587 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700588 // Close the send stream
589 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700590
Girish Gowdra3f974912020-03-23 20:35:18 -0700591 return nil
592}
593
594func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700595 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700596 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
597 if err != nil {
598 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
599 }
600 if indications == nil {
601 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
602 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700603 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700604 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400605}
606
607// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
608func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
609 switch indication.Data.(type) {
610 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
611 return true
612
613 default:
614 return false
615 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700616}
617
David K. Bainbridge794735f2020-02-11 21:01:37 -0800618func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700619 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000620 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530621 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530623 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700624 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000625 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000626 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530627 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000628 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800629 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000630 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800631 }
632 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633}
634
David K. Bainbridge794735f2020-02-11 21:01:37 -0800635// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530636func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700637 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700638 switch indication.Data.(type) {
639 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000640 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
641 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700642 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 -0800643 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400644 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800645 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700646 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000647 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
648 defer span.Finish()
649
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800651 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100652 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400653 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800654 }
655 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000656 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000658 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
659 defer span.Finish()
660
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700661 intfOperInd := indication.GetIntfOperInd()
662 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800663 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100664 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400665 _ = 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 -0800666 }
667 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668 } else if intfOperInd.GetType() == "pon" {
669 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
670 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100672 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400673 _ = 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 -0800674 }
675 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000676 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700677 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000678 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530679 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530680 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700681 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000682 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
683 defer span.Finish()
684
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700685 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000686 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800687 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800688 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700689 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000690 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
691 defer span.Finish()
692
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000694 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800695 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800696 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000698 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
699 defer span.Finish()
700
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 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 -0800703 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000704 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400705 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800706 }
707 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700708 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000709 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
710 defer span.Finish()
711
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700712 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000713 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700714 "intf-type": pktInd.IntfId,
715 "intf-id": pktInd.IntfId,
716 "gem-port-id": pktInd.GemportId,
717 "port-no": pktInd.PortNo,
718 "device-id": dh.device.Id,
719 })
720
721 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000722 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700723 "intf-type": pktInd.IntfId,
724 "intf-id": pktInd.IntfId,
725 "gem-port-id": pktInd.GemportId,
726 "port-no": pktInd.PortNo,
727 "packet": hex.EncodeToString(pktInd.Pkt),
728 "device-id": dh.device.Id,
729 })
730 }
731
David K. Bainbridge794735f2020-02-11 21:01:37 -0800732 go func() {
733 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400734 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800735 }
736 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700737 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000738 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
739 defer span.Finish()
740
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700741 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700742 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700743 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000744 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
745 defer span.Finish()
746
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700747 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000748 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700749 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000750 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
751 defer span.Finish()
752
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700753 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000754 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
755 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700756 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530757}
758
759// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530760func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530761 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000762 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530763
Girish Gowdra618fa572021-09-01 17:19:29 -0700764 // instantiate the mcast handler routines.
765 for i := range dh.incomingMcastFlowOrGroup {
766 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
767 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
768 if !dh.mcastHandlerRoutineActive[i] {
769 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
770 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
771 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
772 // for incoming mcast flow/group to be processed serially.
773 dh.mcastHandlerRoutineActive[i] = true
774 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
775 }
776 }
777
Girish Gowdru0c588b22019-04-23 23:24:56 -0400778 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400779 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400780 DeviceId: dh.device.Id,
781 OperStatus: voltha.OperStatus_ACTIVE,
782 ConnStatus: voltha.ConnectStatus_REACHABLE,
783 }); err != nil {
784 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400785 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000786
787 //Clear olt communication failure event
788 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
789 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700790 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000791 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
792
Girish Gowdru0c588b22019-04-23 23:24:56 -0400793 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530794}
795
796// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530797func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000798 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400799
khenaidoo106c61a2021-08-11 18:05:46 -0400800 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400801 if err != nil || device == nil {
802 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000803 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400804 }
805
806 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400807
808 //Update the device oper state and connection status
809 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800810 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400811 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800812 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400813
khenaidoodc2116e2021-10-19 17:33:19 -0400814 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400815 DeviceId: cloned.Id,
816 OperStatus: cloned.OperStatus,
817 ConnStatus: cloned.ConnectStatus,
818 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000819 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400820 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400821
822 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400823 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400824 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000825 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400826 }
827 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400828 // Update onu state as down in onu adapter
829 onuInd := oop.OnuIndication{}
830 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400831
832 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
833 if err != nil {
834 return err
835 }
836 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400837 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400838 DeviceId: onuDevice.Id,
839 OnuIndication: &onuInd,
840 })
841 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800842 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400843 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400844 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800845 "onu-indicator": onuInd,
846 "device-type": onuDevice.Type,
847 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700848 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800849 } else {
850 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 -0700851 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400852 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800853 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700854 /* Discovered ONUs entries need to be cleared , since after OLT
855 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530856 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800857 dh.lockDevice.Unlock()
858
Neha Sharma96b7bf22020-06-15 10:37:32 +0000859 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700860 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530861}
862
863// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530864func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400865 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000866
867 // if the connection is already available, close the previous connection (olt reboot case)
868 if dh.clientCon != nil {
869 if err = dh.clientCon.Close(); err != nil {
870 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
871 } else {
872 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
873 }
874 }
875
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530876 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +0000877 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000878 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
879 grpc.WithInsecure(),
880 grpc.WithBlock(),
881 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000882 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000883 )),
884 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000885 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000886 )))
887
888 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530889 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530890 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000891 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400892 }
893 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530894}
895
896// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530897func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400898 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530899 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400900 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530901}
902
903// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530904func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530905 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000906 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400907
908 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400909 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530910 if err != nil || device == nil {
911 /*TODO: needs to handle error scenarios */
912 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
913 }
914 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000915 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400916
917 cloned := proto.Clone(device).(*voltha.Device)
918 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
919 cloned.OperStatus = voltha.OperStatus_UNKNOWN
920 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400921
khenaidoodc2116e2021-10-19 17:33:19 -0400922 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400923 DeviceId: cloned.Id,
924 OperStatus: cloned.OperStatus,
925 ConnStatus: cloned.ConnectStatus,
926 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530927 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 -0400928 }
929
Chaitrashree G S44124192019-08-07 20:21:36 -0400930 // 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 +0530931 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400932 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530933 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400934 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400935 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
936 // all the modules initialized and ready to handle incoming ONUs.
937
Thomas Lee S985938d2020-05-04 11:40:41 +0530938 err = dh.initializeDeviceHandlerModules(ctx)
939 if err != nil {
940 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 -0400941 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400942
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700943 go startHeartbeatCheck(ctx, dh)
944
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400945 return nil
946 }
947
khenaidoo106c61a2021-08-11 18:05:46 -0400948 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400949 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400950 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400951 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400952 }
khenaidoo106c61a2021-08-11 18:05:46 -0400953 dh.populateActivePorts(ctx, ports.Items)
954 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400955 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400956 }
957
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400958 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530959 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 -0400960 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530961
Neha Sharma96b7bf22020-06-15 10:37:32 +0000962 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000963
964 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000965 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000966 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700967
968 go startHeartbeatCheck(ctx, dh)
969
cuilin20187b2a8c32019-03-26 19:52:28 -0700970 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530971}
972
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400973func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700974 var err error
975 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400976
977 if err != nil {
978 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
979 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700980 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
981 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +0000982 // +1 is for NNI
983 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
984 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700985 var i uint32
yasin saplid0566272021-12-21 09:10:30 +0000986 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
987 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
988 // There is only one NNI manager since multiple NNI is not supported for now
989 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700990 // Instantiate resource manager
991 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 -0700992 return olterrors.ErrResourceManagerInstantiating
993 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400994 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700995 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
996 // the KV store to manage mcast group data. Provide the first instance (0th index)
997 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
998 return olterrors.ErrGroupManagerInstantiating
999 }
yasin saplid0566272021-12-21 09:10:30 +00001000 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001001 // Instantiate flow manager
1002 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001003 //Continue to check the rest of the ports
1004 logger.Errorw(ctx, "error-initializing-flow-manager-for-intf", log.Fields{"intfID": i, "device-id": dh.device.Id})
1005 } else {
1006 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001007 }
1008 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001009 /* TODO: Instantiate Alarm , stats , BW managers */
1010 /* Instantiating Event Manager to handle Alarms and KPIs */
1011 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1012
1013 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001014 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001015
1016 return nil
1017
1018}
1019
Neha Sharma96b7bf22020-06-15 10:37:32 +00001020func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001021 var err error
1022 var deviceInfo *oop.DeviceInfo
1023
Neha Sharma8f4e4322020-08-06 10:51:53 +00001024 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001025
1026 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001027 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001028 }
1029 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001030 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001031 }
1032
Neha Sharma96b7bf22020-06-15 10:37:32 +00001033 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001034 dh.device.Root = true
1035 dh.device.Vendor = deviceInfo.Vendor
1036 dh.device.Model = deviceInfo.Model
1037 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1038 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1039 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1040
1041 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001042 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001043 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001044 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001045 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001046 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001047 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001048 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001049 dh.device.MacAddress = genmac
1050 } else {
1051 dh.device.MacAddress = deviceInfo.DeviceId
1052 }
1053
1054 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001055 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001056 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001057 }
1058
1059 return deviceInfo, nil
1060}
1061
Neha Sharma96b7bf22020-06-15 10:37:32 +00001062func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001063 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001064
1065 defer func() {
1066 dh.lockDevice.Lock()
1067 dh.isCollectorActive = false
1068 dh.lockDevice.Unlock()
1069 }()
1070
1071 dh.lockDevice.Lock()
1072 dh.isCollectorActive = true
1073 dh.lockDevice.Unlock()
1074
Naga Manjunath7615e552019-10-11 22:35:47 +05301075 for {
1076 select {
1077 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001078 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301079 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001080 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001081
khenaidoo106c61a2021-08-11 18:05:46 -04001082 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001083 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001084 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001085 continue
1086 }
khenaidoo106c61a2021-08-11 18:05:46 -04001087 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301088 // NNI Stats
1089 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001090 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301091 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001093 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001094 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301095 }
1096 // PON Stats
1097 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001098 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301099 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1100 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001101 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001102 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301103 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001104 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001105
yasin sapli9e4c5092022-02-01 13:52:33 +00001106 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001107 if len(onuGemInfoLst) > 0 {
1108 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001109 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001110 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301111 }
1112 }
1113 }
1114}
1115
Mahir Gunyela2e68702022-12-07 00:00:42 -08001116// AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301117func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001118 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301120 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301121
1122 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001123 cgClient, err := dh.coreClient.GetCoreServiceClient()
1124 if err != nil {
1125 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1126 return
1127 }
1128
1129 // Now, set the initial PM configuration for that device
1130 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001131 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301132 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301133}
1134
Mahir Gunyela2e68702022-12-07 00:00:42 -08001135// GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001136func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1137 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001138 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301139 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001140 HwDesc: "open_pon",
1141 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001142 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001143 },
1144 SwitchFeatures: &of.OfpSwitchFeatures{
1145 NBuffers: 256,
1146 NTables: 2,
1147 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1148 of.OfpCapabilities_OFPC_TABLE_STATS |
1149 of.OfpCapabilities_OFPC_PORT_STATS |
1150 of.OfpCapabilities_OFPC_GROUP_STATS),
1151 },
1152 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301153}
1154
khenaidoo106c61a2021-08-11 18:05:46 -04001155// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001156func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001157 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001158 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001159 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001160 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08001161 if dh.flowMgr == nil || dh.flowMgr[ifID] == nil {
1162 return nil, olterrors.NewErrNotFound("no-flow-manager-found", log.Fields{"intf-id": ifID, "parent-device-id": request.ParentDeviceId, "child-device-id": request.DeviceId}, nil).Log()
1163 }
khenaidoo106c61a2021-08-11 18:05:46 -04001164 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Mahir Gunyela2e68702022-12-07 00:00:42 -08001165
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001166}
1167
Neha Sharma96b7bf22020-06-15 10:37:32 +00001168func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001169 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 -07001170 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001171 var deviceID string
1172 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001173 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001174
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001175 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001176 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001177 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 -07001178 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1179 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001180
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001181 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301182
1183 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1184
Neha Sharma96b7bf22020-06-15 10:37:32 +00001185 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 -07001186 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001187
khenaidoodc2116e2021-10-19 17:33:19 -04001188 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001189 ParentId: dh.device.Id,
1190 OnuId: omciInd.OnuId,
1191 ParentPortNo: ponPort,
1192 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001193 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301194 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001195 "intf-id": omciInd.IntfId,
1196 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001197 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001198 deviceType = onuDevice.Type
1199 deviceID = onuDevice.Id
1200 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001201 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001202 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001203 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001204 } else {
1205 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001206 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 +05301207 deviceType = onuInCache.(*OnuDevice).deviceType
1208 deviceID = onuInCache.(*OnuDevice).deviceID
1209 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001210 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001211 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001212
khenaidoodc2116e2021-10-19 17:33:19 -04001213 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001214 ParentDeviceId: proxyDeviceID,
1215 ChildDeviceId: deviceID,
1216 Message: omciInd.Pkt,
1217 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301218 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001219 "source": dh.openOLT.config.AdapterEndpoint,
1220 "device-type": deviceType,
1221 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001223 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001224 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001225 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301226}
1227
khenaidoo106c61a2021-08-11 18:05:46 -04001228// //ProcessInterAdapterMessage sends the proxied messages to the target device
1229// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1230// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001231// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001232// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001233// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001234// return dh.handleInterAdapterOmciMsg(ctx, msg)
1235// }
1236// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1237// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001238
kesavandb9f54fd2021-11-25 20:08:04 +05301239// ProxyOmciRequests sends the proxied OMCI message to the target device
1240func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301241 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1242 return status.Error(codes.Unavailable, "OLT unreachable")
1243 }
kesavandb9f54fd2021-11-25 20:08:04 +05301244 if omciMsgs.GetProxyAddress() == nil {
1245 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1246 if err != nil {
1247 return olterrors.NewErrNotFound("onu", log.Fields{
1248 "parent-device-id": dh.device.Id,
1249 "child-device-id": omciMsgs.ChildDeviceId}, err)
1250 }
1251 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1252 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1253 return olterrors.NewErrCommunication("send-failed", log.Fields{
1254 "parent-device-id": dh.device.Id,
1255 "child-device-id": omciMsgs.ChildDeviceId}, err)
1256 }
1257 } else {
1258 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1259 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1260 return olterrors.NewErrCommunication("send-failed", log.Fields{
1261 "parent-device-id": dh.device.Id,
1262 "child-device-id": omciMsgs.ChildDeviceId}, err)
1263 }
1264 }
1265 return nil
1266}
1267
1268func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1269 var intfID uint32
1270 var onuID uint32
1271 var connectStatus common.ConnectStatus_Types
1272 if onuDevice != nil {
1273 intfID = onuDevice.ProxyAddress.GetChannelId()
1274 onuID = onuDevice.ProxyAddress.GetOnuId()
1275 connectStatus = onuDevice.ConnectStatus
1276 } else {
1277 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1278 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1279 connectStatus = omciMsgs.GetConnectStatus()
1280 }
1281 if connectStatus != voltha.ConnectStatus_REACHABLE {
1282 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1283
1284 return olterrors.NewErrCommunication("unreachable", log.Fields{
1285 "intf-id": intfID,
1286 "onu-id": onuID}, nil)
1287 }
1288
1289 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1290 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1291
1292 onuSecOmciMsgList := omciMsgs.GetMessages()
1293
1294 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1295
1296 var omciMessage *oop.OmciMsg
1297 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1298 hex.Encode(hexPkt, onuSecOmciMsg)
1299 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1300
1301 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1302 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1303 //https://jira.opencord.org/browse/VOL-4604
1304 transid := extractOmciTransactionID(onuSecOmciMsg)
1305 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1306 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1307
1308 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1309 if err != nil {
1310 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1311 "intf-id": intfID,
1312 "onu-id": onuID,
1313 "message": omciMessage}, err)
1314 }
1315 }
1316 return nil
1317}
1318
khenaidoo106c61a2021-08-11 18:05:46 -04001319// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001320func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001321 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 -07001322
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301323 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1324 return status.Error(codes.Unavailable, "OLT unreachable")
1325 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001326 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001327 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001328 if err != nil {
1329 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001330 "parent-device-id": dh.device.Id,
1331 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001332 }
khenaidoo106c61a2021-08-11 18:05:46 -04001333 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1334 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001335 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001336 "parent-device-id": dh.device.Id,
1337 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001338 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001339 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001340 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1341 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001342 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001343 "parent-device-id": dh.device.Id,
1344 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001345 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001346 }
1347 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301348}
1349
khenaidoodc2116e2021-10-19 17:33:19 -04001350func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001351 var intfID uint32
1352 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001353 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001354 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001355 intfID = onuDevice.ProxyAddress.GetChannelId()
1356 onuID = onuDevice.ProxyAddress.GetOnuId()
1357 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001358 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001359 intfID = omciMsg.GetProxyAddress().GetChannelId()
1360 onuID = omciMsg.GetProxyAddress().GetOnuId()
1361 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001362 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001363 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001364 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 -08001365
Thomas Lee S94109f12020-03-03 16:39:29 +05301366 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001367 "intf-id": intfID,
1368 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001369 }
1370
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001371 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1372 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301373 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001374 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001375 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1376 hex.Encode(hexPkt, omciMsg.Message)
1377 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1378
1379 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1380 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1381 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001382 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001383 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001384
Neha Sharma8f4e4322020-08-06 10:51:53 +00001385 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001386 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301387 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001388 "intf-id": intfID,
1389 "onu-id": onuID,
1390 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001391 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001392 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001393}
1394
David K. Bainbridge794735f2020-02-11 21:01:37 -08001395func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301396 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 +00001397 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001398 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001399 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001400 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301401 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301402 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001403 st, _ := status.FromError(err)
1404 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001405 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1406
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001407 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301408 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001409 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001410 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001411 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001412 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001413 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001414}
1415
Mahir Gunyela2e68702022-12-07 00:00:42 -08001416// getChildDevice function can be used in general to get child device, if not found in cache the function will
1417// get from core and update the cache and return the child device.
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301418func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1419 var InCacheOnuDev *OnuDevice
1420 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1421 if onuInCache.(*OnuDevice).serialNumber == sn {
1422 InCacheOnuDev = onuInCache.(*OnuDevice)
1423 return false
1424 }
1425 return true
1426 })
1427 //Got the onu device from cache return
1428 if InCacheOnuDev != nil {
1429 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1430 return InCacheOnuDev
1431 }
1432 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1433 ParentId: dh.device.Id,
1434 SerialNumber: sn,
1435 ParentPortNo: parentPortNo,
1436 })
1437 //No device found in core return nil
1438 if onuDevice == nil {
1439 return nil
1440 }
1441 onuID := onuDevice.ProxyAddress.OnuId
1442 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1443 onuKey := dh.formOnuKey(intfID, onuID)
1444
1445 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1446 dh.onus.Store(onuKey, onuDev)
1447 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1448 return onuDev
1449}
1450
1451func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001452 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001453 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301454 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001455
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301456 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1457 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1458 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1459 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1460 if onuDev != nil {
1461 var onuGemInfo *rsrcMgr.OnuGemInfo
1462 var err error
1463 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1464 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1465 return false, err
1466 }
1467 if onuGemInfo != nil {
1468 for _, uni := range onuGemInfo.UniPorts {
1469 uniID := plt.UniIDFromPortNum(uni)
1470 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1471 if len(tpIDs) != 0 {
1472 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1473 tpInstExists = true
1474 break
1475 }
1476 }
1477 }
1478 }
1479 return tpInstExists, nil
1480 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301481
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301482 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1483 ParentId: dh.device.Id,
1484 SerialNumber: sn,
1485 ParentPortNo: parentPortNo,
1486 })
1487 if onuDevice != nil {
1488 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1489 return true, nil
1490 }
1491 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1492
1493 return false, nil
1494
1495}
1496
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001497// processDiscONULOSClear clears the LOS Alarm if it's needed
1498func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301499 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001500 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301501
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001502 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1503 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1504 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1505 OnuLosRaise event sent for it */
1506 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1507 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1508 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1509 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1510 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1511 "currentIntfId": onuDiscInd.GetIntfId()})
1512 // TODO:: Should we need to ignore raising OnuLosClear event
1513 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301514 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001515 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1516 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1517 alarmInd.LosStatus = statusCheckOff
1518 go func() {
1519 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1520 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1521 }
1522 }()
1523 // stop iterating
1524 return false
1525 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301526 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001527 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301528}
1529
1530func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
1531 channelID := onuDiscInd.GetIntfId()
1532 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1533
1534 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
1535 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1536
1537 tpInstExists, errtp := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1538 if errtp != nil {
1539 return errtp
1540 }
1541 if tpInstExists {
1542 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001543 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001544 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001545 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001546 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1547
1548 // if the ONU existed, handle the LOS Alarm
1549 if existing {
1550
1551 if inProcess.(bool) {
1552 // if we're currently processing the ONU on a different thread, do nothing
1553 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1554 return nil
1555 }
1556 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1557 // then continue processing it
1558 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1559
1560 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001561 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301562 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001563
1564 defer func() {
1565 // once the function completes set the value to false so that
1566 // we know the processing has inProcess.
1567 // Note that this is done after checking if we are already processing
1568 // to avoid changing the value from a different thread
1569 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1570 dh.discOnus.Store(sn, false)
1571 }()
1572
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001573 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001574
1575 // check the ONU is already know to the OLT
1576 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001577 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001578 ParentId: dh.device.Id,
1579 SerialNumber: sn,
1580 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001581
1582 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001583 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 -08001584 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001585 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 -08001586 switch e.Code() {
1587 case codes.Internal:
1588 // this probably means NOT FOUND, so just create a new device
1589 onuDevice = nil
1590 case codes.DeadlineExceeded:
1591 // if the call times out, cleanup and exit
1592 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001593 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001594 }
1595 }
1596 }
1597
1598 if onuDevice == nil {
1599 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001600 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001601 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001602 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001603 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001604
Neha Sharma96b7bf22020-06-15 10:37:32 +00001605 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001606
1607 if err != nil {
1608 // if we can't create an ID in resource manager,
1609 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001610 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001611 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001612 "pon-intf-id": ponintfid,
1613 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001614 }
1615
khenaidoodc2116e2021-10-19 17:33:19 -04001616 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001617 ParentId: dh.device.Id,
1618 ParentPortNo: parentPortNo,
1619 ChannelId: channelID,
1620 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1621 SerialNumber: sn,
1622 OnuId: onuID,
1623 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001624 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001625 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 +05301626 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001627 "pon-intf-id": ponintfid,
1628 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001629 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001630 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 -07001631 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001632 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001633 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301634 log.Fields{"onuDevice": onuDevice,
1635 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001636 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301637 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001638 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001639
khenaidoo106c61a2021-08-11 18:05:46 -04001640 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1641 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1642 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1643 cancel()
1644 if err != nil {
1645 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1646 }
1647
Matteo Scandolo945e4012019-12-12 14:16:11 -08001648 // we can now use the existing ONU Id
1649 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001650 //Insert the ONU into cache to use in OnuIndication.
1651 //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 +00001652 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001653 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301654 "intfId": onuDiscInd.GetIntfId(),
1655 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001656 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001657
khenaidoo106c61a2021-08-11 18:05:46 -04001658 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301659 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001660 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301661 log.Fields{"onu": onuDev,
1662 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001663
khenaidoodc2116e2021-10-19 17:33:19 -04001664 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001665 DeviceId: onuDevice.Id,
1666 ParentDeviceId: dh.device.Id,
1667 OperStatus: common.OperStatus_DISCOVERED,
1668 ConnStatus: common.ConnectStatus_REACHABLE,
1669 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301670 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001671 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001672 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001673 }
khenaidoo106c61a2021-08-11 18:05:46 -04001674
Neha Sharma96b7bf22020-06-15 10:37:32 +00001675 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001676 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301677 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001679 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001680 }
1681 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001682}
1683
Mahir Gunyelb0046752021-02-26 13:51:05 -08001684func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001685
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001686 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001687 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001688 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001689 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001690 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301691 log.Fields{"onuId": onuInd.OnuId,
1692 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301693 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001694 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001695 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301696
David K. Bainbridge794735f2020-02-11 21:01:37 -08001697 errFields := log.Fields{"device-id": dh.device.Id}
1698
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301699 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1700
Mahir Gunyele77977b2019-06-27 05:36:22 -07001701 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1702 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001703 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001704 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001705 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001706 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1707 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001708 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001709 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001710 errFields["onu-id"] = onuInd.OnuId
1711 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001712 }
khenaidoodc2116e2021-10-19 17:33:19 -04001713 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001714 ParentId: dh.device.Id,
1715 SerialNumber: serialNumber,
1716 OnuId: onuInd.OnuId,
1717 ParentPortNo: ponPort,
1718 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001719 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001720
David K. Bainbridge794735f2020-02-11 21:01:37 -08001721 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001722 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001723 }
1724
David K. Bainbridge794735f2020-02-11 21:01:37 -08001725 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001727 "previousIntfId": onuDevice.ParentPortNo,
1728 "currentIntfId": ponPort})
1729 }
1730
1731 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001732 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301733 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1734 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301735 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001736 }
1737 if !foundInCache {
1738 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1739
khenaidoo106c61a2021-08-11 18:05:46 -04001740 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 -08001741
1742 }
kesavand7cf3a052020-08-28 12:49:18 +05301743 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001744 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001745 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301746 }
1747 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001748 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001749 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001750 }
1751 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001752}
1753
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001755 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 -07001756 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1757 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1758 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1759 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001760 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001761 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1762 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001763 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001764 onuInd.OperState = "down"
1765 }
1766 }
1767
David K. Bainbridge794735f2020-02-11 21:01:37 -08001768 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001769 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001770 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 -04001771
khenaidoodc2116e2021-10-19 17:33:19 -04001772 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001773 DeviceId: onuDevice.Id,
1774 OnuIndication: onuInd,
1775 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001776 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301777 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001778 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001779 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001780 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001781 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001782 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001783 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001784 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001785 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001786 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001787}
1788
cuilin20187b2a8c32019-03-26 19:52:28 -07001789func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1790 if serialNum != nil {
1791 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001792 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001793 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001794}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001795func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1796 decodedStr, err := hex.DecodeString(serialNum[4:])
1797 if err != nil {
1798 return nil, err
1799 }
1800 return &oop.SerialNumber{
1801 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001802 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001803 }, nil
1804}
cuilin20187b2a8c32019-03-26 19:52:28 -07001805
1806func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001807 if len(vendorSpecific) > 3 {
1808 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1809 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1810 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1811 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1812 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1813 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1814 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1815 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1816 return tmp
1817 }
1818 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001819}
1820
Mahir Gunyela2e68702022-12-07 00:00:42 -08001821// UpdateFlowsBulk upates the bulk flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001822func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301823 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001824}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001825
Mahir Gunyela2e68702022-12-07 00:00:42 -08001826// GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001827func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1828 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301829 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001830 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301831 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001832
khenaidoodc2116e2021-10-19 17:33:19 -04001833 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001834 ParentId: dh.device.Id,
1835 OnuId: onuID,
1836 ParentPortNo: parentPort,
1837 })
1838
Girish Gowdru0c588b22019-04-23 23:24:56 -04001839 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001840 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001841 "intf-id": parentPort,
1842 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001843 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001844 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 -08001845 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301846}
1847
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001848// SendPacketInToCore sends packet-in to core
1849// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1850// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001851func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001852 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001853 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001854 "port": logicalPort,
1855 "packet": hex.EncodeToString(packetPayload),
1856 "device-id": dh.device.Id,
1857 })
1858 }
khenaidoo106c61a2021-08-11 18:05:46 -04001859
khenaidoodc2116e2021-10-19 17:33:19 -04001860 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001861 DeviceId: dh.device.Id,
1862 Port: logicalPort,
1863 Packet: packetPayload,
1864 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301865 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001866 "source": "adapter",
1867 "destination": "core",
1868 "device-id": dh.device.Id,
1869 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001870 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001871 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001872 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001873 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001874 "packet": hex.EncodeToString(packetPayload),
1875 "device-id": dh.device.Id,
1876 })
1877 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001878 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001879}
1880
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001881// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001882func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001883 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001884
1885 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1886 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001887 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001888 }
1889
Kent Hagermane6ff1012020-07-14 15:07:53 -04001890 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001891 metrics := dh.metrics.GetSubscriberMetrics()
1892 for _, m := range pmConfigs.Metrics {
1893 metrics[m.Name].Enabled = m.Enabled
1894
1895 }
1896 }
1897}
1898
khenaidoodc2116e2021-10-19 17:33:19 -04001899func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001900 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001901 var errorsList []error
1902
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001903 if dh.getDeviceDeletionInProgressFlag() {
1904 // The device itself is going to be reset as part of deletion. So nothing to be done.
1905 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1906 return nil
1907 }
1908
Girish Gowdru0c588b22019-04-23 23:24:56 -04001909 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001910 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001911 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001912
Neha Sharma96b7bf22020-06-15 10:37:32 +00001913 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301914 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001915 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301916 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001917 if flow_utils.HasGroup(flow) {
1918 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1919 } else {
Mahir Gunyela2e68702022-12-07 00:00:42 -08001920 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
1921 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1922 } else {
1923 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
1924 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001925 }
Girish Gowdracefae192020-03-19 18:14:10 -07001926 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01001927 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
1928 //The flow we want to remove is not there, there is no need to throw an error
1929 logger.Warnw(ctx, "flow-to-remove-not-found",
1930 log.Fields{
1931 "ponIf": intfID,
1932 "flowToRemove": flow,
1933 "error": err,
1934 })
1935 } else {
1936 errorsList = append(errorsList, err)
1937 }
Girish Gowdracefae192020-03-19 18:14:10 -07001938 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001939 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301940
1941 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00001942 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001943 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301944 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001945 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301946 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001947 if flow_utils.HasGroup(flow) {
1948 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1949 } else {
yasin saplid0566272021-12-21 09:10:30 +00001950 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001951 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1952 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1953 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1954 } else {
yasin saplid0566272021-12-21 09:10:30 +00001955 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001956 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001957 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001958 if err != nil {
1959 errorsList = append(errorsList, err)
1960 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301961 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001962 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001963
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001964 return errorsList
1965}
1966
1967func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1968 var err error
1969 var errorsList []error
1970
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001971 if dh.getDeviceDeletionInProgressFlag() {
1972 // The device itself is going to be reset as part of deletion. So nothing to be done.
1973 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1974 return nil
1975 }
1976
Girish Gowdracefae192020-03-19 18:14:10 -07001977 // 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 +00001978 if groups != nil {
1979 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001980 // err = dh.groupMgr.AddGroup(ctx, group)
1981 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001982 if err != nil {
1983 errorsList = append(errorsList, err)
1984 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001985 }
1986 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001987 // err = dh.groupMgr.ModifyGroup(ctx, group)
1988 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001989 if err != nil {
1990 errorsList = append(errorsList, err)
1991 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001992 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001993 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001994 // err = dh.groupMgr.DeleteGroup(ctx, group)
1995 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001996 if err != nil {
1997 errorsList = append(errorsList, err)
1998 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001999 }
2000 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002001
2002 return errorsList
2003}
2004
Mahir Gunyela2e68702022-12-07 00:00:42 -08002005// UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04002006func (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 -07002007
2008 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07002009
2010 if dh.getDeviceDeletionInProgressFlag() {
2011 // The device itself is going to be reset as part of deletion. So nothing to be done.
2012 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2013 return nil
2014 }
2015
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002016 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2017 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2018 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002019 if len(errorsList) > 0 {
2020 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2021 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002022 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002023 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302024}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002025
Mahir Gunyela2e68702022-12-07 00:00:42 -08002026// DisableDevice disables the given device
2027// It marks the following for the given device:
2028// Device-Handler Admin-State : down
2029// Device Port-State: UNKNOWN
2030// Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002031func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002032 /* On device disable ,admin state update has to be done prior sending request to agent since
2033 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002034 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002035 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002036 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002037 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002038 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002039 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002040 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002041 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002042 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002043 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302044
2045 dh.discOnus = sync.Map{}
2046 dh.onus = sync.Map{}
2047
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002048 dh.lockDevice.RLock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302049 //stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002050 if dh.isCollectorActive {
2051 dh.stopCollector <- true
2052 }
2053 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302054
Neha Sharma96b7bf22020-06-15 10:37:32 +00002055 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002056 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05302057 //Update device Admin state
2058 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002059
kdarapu1afeceb2020-02-12 01:38:09 -05002060 // 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 -04002061 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002062 DeviceId: cloned.Id,
2063 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2064 OperStatus: voltha.OperStatus_UNKNOWN,
2065 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002066 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002067 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002068 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002069 return nil
2070}
2071
Neha Sharma96b7bf22020-06-15 10:37:32 +00002072func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002073 // Update onu state as unreachable in onu adapter
2074 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302075 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002076
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002077 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002078 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002079 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002080 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 -04002081 }
2082 if onuDevices != nil {
2083 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002084 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002085 DeviceId: onuDevice.Id,
2086 OnuIndication: &onuInd,
2087 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002088 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002089 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002090 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002091 }
2092
2093 }
2094 }
2095
2096}
2097
Mahir Gunyela2e68702022-12-07 00:00:42 -08002098// ReenableDevice re-enables the olt device after disable
2099// It marks the following for the given device:
2100// Device-Handler Admin-State : up
2101// Device Port-State: ACTIVE
2102// Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002103func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002104 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302105 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002106 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302107 }
2108 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002109 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002110
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002111 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002112 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002113 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002114 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002115 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2116 } else {
2117 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2118 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2119 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002120 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002121 if retError == nil {
2122 //Update the device oper status as ACTIVE
2123 device.OperStatus = voltha.OperStatus_ACTIVE
2124 } else {
2125 //Update the device oper status as FAILED
2126 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002127 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002128 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002129
khenaidoodc2116e2021-10-19 17:33:19 -04002130 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002131 DeviceId: device.Id,
2132 OperStatus: device.OperStatus,
2133 ConnStatus: device.ConnectStatus,
2134 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302135 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002136 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002137 "connect-status": device.ConnectStatus,
2138 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002139 }
kesavand39e0aa32020-01-28 20:58:50 -05002140
Neha Sharma96b7bf22020-06-15 10:37:32 +00002141 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002142
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002143 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002144}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002145
npujarec5762e2020-01-01 14:08:48 +05302146func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002147 var uniID uint32
2148 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302149 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002150 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002151 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002152 /* Delete tech-profile instance from the KV store */
Mahir Gunyela2e68702022-12-07 00:00:42 -08002153 if dh.flowMgr == nil || dh.flowMgr[onu.IntfID] == nil {
2154 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu-no-flowmng", log.Fields{"onu-id": onu.OnuID})
2155 } else {
2156 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
2157 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
2158 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002159 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002160 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002161 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002162 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002163 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002164 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00002165 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002166 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002167 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002168 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00002169 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002170 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302171 }
yasin saplibddc2d72022-02-08 13:10:17 +00002172 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2173 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002174 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302175 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002176 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002177 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002178 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 +00002179 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002180 }
2181 return nil
2182}
2183
Devmalya Paul495b94a2019-08-27 19:42:00 -04002184// 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 +05302185func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002186 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002187 /* Clear the KV store data associated with the all the UNI ports
2188 This clears up flow data and also resource map data for various
2189 other pon resources like alloc_id and gemport_id
2190 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002191
2192 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002193 var wg sync.WaitGroup
2194 wg.Add(1) // for the mcast routine below to finish
2195 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2196 for _, flMgr := range dh.flowMgr {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002197 if flMgr != nil {
2198 wg.Add(1) // for the flow handler routine below to finish
2199 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2200 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002201 }
2202 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2203 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2204 } else {
2205 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2206 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002207
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002208 dh.cleanupDeviceResources(ctx)
2209 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002210
Himani Chawla49a5d562020-11-25 11:53:44 +05302211 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002212 // Stop the Stats collector
2213 if dh.isCollectorActive {
2214 dh.stopCollector <- true
2215 }
2216 // stop the heartbeat check routine
2217 if dh.isHeartbeatCheckActive {
2218 dh.stopHeartbeatCheck <- true
2219 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302220 // Stop the read indication only if it the routine is active
2221 if dh.isReadIndicationRoutineActive {
2222 dh.stopIndications <- true
2223 }
2224 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002225 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002226 //Reset the state
2227 if dh.Client != nil {
2228 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302229 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002230 }
2231 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002232 // There is no need to update the core about operation status and connection status of the OLT.
2233 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2234 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2235 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002236
khenaidoo7eb2d672021-10-22 19:08:50 -04002237 // Stop the adapter grpc clients for that parent device
2238 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002239 return nil
2240}
Kent Hagermane6ff1012020-07-14 15:07:53 -04002241func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002242
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002243 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302244 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002245 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002246 var err error
yasin sapli9e4c5092022-02-01 13:52:33 +00002247 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002248 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002249 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002250 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002251 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302252 }
2253 }
yasin saplibddc2d72022-02-08 13:10:17 +00002254 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx)
2255 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002256 dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002257 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2258 logger.Debug(ctx, err)
2259 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002260 }
yasin saplibddc2d72022-02-08 13:10:17 +00002261 // Clean up NNI manager's data
2262 _ = dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002263 }
A R Karthick1f85b802019-10-11 05:06:05 +00002264
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002265 // Take one final sweep at cleaning up KV store for the OLT device
2266 // Clean everything at <base-path-prefix>/openolt/<device-id>
2267 kvClient, err := kvstore.NewEtcdClient(ctx, dh.openOLT.KVStoreAddress, rsrcMgr.KvstoreTimeout, log.FatalLevel)
2268 if err == nil {
2269 kvBackend := &db.Backend{
2270 Client: kvClient,
2271 StoreType: dh.openOLT.KVStoreType,
2272 Address: dh.openOLT.KVStoreAddress,
2273 Timeout: rsrcMgr.KvstoreTimeout,
2274 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, dh.cm.Backend.PathPrefix, dh.device.Id)}
2275 _ = kvBackend.DeleteWithPrefix(ctx, "")
2276 }
2277
Devmalya Paul495b94a2019-08-27 19:42:00 -04002278 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302279 dh.onus.Range(func(key interface{}, value interface{}) bool {
2280 dh.onus.Delete(key)
2281 return true
2282 })
2283
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002284 /*Delete discovered ONU map for the device*/
2285 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2286 dh.discOnus.Delete(key)
2287 return true
2288 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002289}
2290
Mahir Gunyela2e68702022-12-07 00:00:42 -08002291// RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002292func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002293 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302294 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002295 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002296 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002297 return nil
2298}
2299
David K. Bainbridge794735f2020-02-11 21:01:37 -08002300func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002301 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002302 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002303 "packet-indication": *packetIn,
2304 "device-id": dh.device.Id,
2305 "packet": hex.EncodeToString(packetIn.Pkt),
2306 })
2307 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002308 if dh.flowMgr == nil || dh.flowMgr[packetIn.IntfId] == nil {
2309 return olterrors.NewErrNotFound("flow-manager", log.Fields{"intf-id": packetIn.IntfId, "packet": hex.EncodeToString(packetIn.Pkt)}, nil)
2310 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002311 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002312 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002313 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002314 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002315 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002316 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002317 "logical-port-num": logicalPortNum,
2318 "device-id": dh.device.Id,
2319 "packet": hex.EncodeToString(packetIn.Pkt),
2320 })
2321 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002322
khenaidoodc2116e2021-10-19 17:33:19 -04002323 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002324 DeviceId: dh.device.Id,
2325 Port: logicalPortNum,
2326 Packet: packetIn.Pkt,
2327 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302328 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002329 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302330 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002331 "device-id": dh.device.Id,
2332 "packet": hex.EncodeToString(packetIn.Pkt),
2333 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002334 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002335
Matteo Scandolo92186242020-06-12 10:54:18 -07002336 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002337 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002338 "packet": hex.EncodeToString(packetIn.Pkt),
2339 "device-id": dh.device.Id,
2340 })
2341 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002342 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002343}
2344
Mahir Gunyela2e68702022-12-07 00:00:42 -08002345// PacketOutNNI sends packet-out from VOLTHA to OLT on the NNI provided
2346func (dh *DeviceHandler) PacketOutNNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2347 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
2348 if err != nil {
2349 return olterrors.NewErrInvalidValue(log.Fields{
2350 "egress-nni-port": egressPortNo,
2351 "device-id": dh.device.Id,
2352 }, err)
2353 }
2354 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
2355
2356 if logger.V(log.DebugLevel) {
2357 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
2358 "uplink-pkt": uplinkPkt,
2359 "packet": hex.EncodeToString(packet.Data),
2360 "device-id": dh.device.Id,
2361 })
2362 }
2363
2364 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
2365 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2366 "packet": hex.EncodeToString(packet.Data),
2367 "device-id": dh.device.Id,
2368 }, err)
2369 }
2370 return nil
2371}
2372
2373// PacketOutUNI sends packet-out from VOLTHA to OLT on the UNI provided
2374func (dh *DeviceHandler) PacketOutUNI(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
2375 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2376 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
2377 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2378 // Do not packet-out lldp packets on uni port.
2379 // ONOS has no clue about uni/nni ports, it just packets out on all
2380 // available ports on the Logical Switch. It should not be interested
2381 // in the UNI links.
2382 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
2383 "device-id": dh.device.Id,
2384 })
2385 return nil
2386 }
2387 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2388 if innerEthType == 0x8100 {
2389 // q-in-q 802.1ad or 802.1q double tagged packet.
2390 // slice out the outer tag.
2391 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
2392 if logger.V(log.DebugLevel) {
2393 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
2394 "packet-data": hex.EncodeToString(packet.Data),
2395 "device-id": dh.device.Id,
2396 })
2397 }
2398 }
2399 }
2400 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2401 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2402 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
2403 var gemPortID uint32
2404 err := olterrors.NewErrNotFound("no-flow-manager-found-for-packet-out", log.Fields{"device-id": dh.device.Id}, nil).(error)
2405 if dh.flowMgr != nil && dh.flowMgr[intfID] != nil {
2406 gemPortID, err = dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
2407 }
2408 if err != nil {
2409 // In this case the openolt agent will receive the gemPortID as 0.
2410 // The agent tries to retrieve the gemPortID in this case.
2411 // This may not always succeed at the agent and packetOut may fail.
2412 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
2413 "intf-id": intfID,
2414 "onu-id": onuID,
2415 "uni-id": uniID,
2416 "packet": hex.EncodeToString(packet.Data),
2417 "device-id": dh.device.Id,
2418 "error": err,
2419 })
2420 }
2421
2422 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
2423 if logger.V(log.DebugLevel) {
2424 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
2425 "egress-port-no": egressPortNo,
2426 "intf-id": intfID,
2427 "onu-id": onuID,
2428 "uni-id": uniID,
2429 "gem-port-id": gemPortID,
2430 "packet": hex.EncodeToString(packet.Data),
2431 "device-id": dh.device.Id,
2432 })
2433 }
2434
2435 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
2436 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
2437 "source": "adapter",
2438 "destination": "onu",
2439 "egress-port-number": egressPortNo,
2440 "intf-id": intfID,
2441 "oni-id": onuID,
2442 "uni-id": uniID,
2443 "gem-port-id": gemPortID,
2444 "packet": hex.EncodeToString(packet.Data),
2445 "device-id": dh.device.Id,
2446 }, err)
2447 }
2448 return nil
2449}
2450
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002451// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002452func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002453 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002454 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002455 "device-id": dh.device.Id,
2456 "egress-port-no": egressPortNo,
2457 "pkt-length": len(packet.Data),
2458 "packet": hex.EncodeToString(packet.Data),
2459 })
2460 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002461
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002462 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
Mahir Gunyela2e68702022-12-07 00:00:42 -08002463 var err error
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002464 if egressPortType == voltha.Port_ETHERNET_UNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002465 err = dh.PacketOutUNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002466 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002467 err = dh.PacketOutNNI(ctx, egressPortNo, packet)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002468 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002469 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302470 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002471 "egressPortType": egressPortType,
2472 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302473 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002474 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002475 }
Mahir Gunyela2e68702022-12-07 00:00:42 -08002476 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002477}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002478
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002479func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2480 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002481}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302482
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002483func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002484
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002485 defer func() {
2486 dh.lockDevice.Lock()
2487 dh.isHeartbeatCheckActive = false
2488 dh.lockDevice.Unlock()
2489 }()
2490
2491 dh.lockDevice.Lock()
2492 dh.isHeartbeatCheckActive = true
2493 dh.lockDevice.Unlock()
2494
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302495 // start the heartbeat check towards the OLT.
2496 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302497 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302498
2499 for {
2500 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2501 select {
2502 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002503 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002504 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002505 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302506 if timerCheck == nil {
2507 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002508 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302509 }
2510 } else {
2511 if timerCheck != nil {
2512 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002513 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302514 }
2515 timerCheck = nil
2516 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302517 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2518 if dh.heartbeatSignature == 0 {
2519 // First time the signature will be 0, update the signture to DB when not found.
2520 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2521 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2522 }
2523 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2524
2525 dh.lockDevice.RLock()
2526 // Stop the read indication only if it the routine is active
2527 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2528 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2529 // on next execution of the readIndication routine.
2530 if !dh.isReadIndicationRoutineActive {
2531 // Start reading indications
2532 go func() {
2533 if err = dh.readIndications(ctx); err != nil {
2534 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2535 }
2536 }()
2537 }
2538 dh.lockDevice.RUnlock()
2539
2540 } else {
2541 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2542 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2543 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2544 go dh.updateStateRebooted(ctx)
2545 }
2546
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302547 }
2548 cancel()
2549 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002550 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302551 return
2552 }
2553 }
2554}
2555
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002556func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002557 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002558 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002559 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2560 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2561 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2562 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2563 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002564 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002565 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2566 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002567 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302568
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302569 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002570 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002571 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002572 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002573 DeviceId: dh.device.Id,
2574 OperStatus: voltha.OperStatus_UNKNOWN,
2575 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2576 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002577 _ = 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 -04002578 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302579 /*
2580 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2581 DeviceId: dh.device.Id,
2582 PortTypeFilter: 0,
2583 OperStatus: voltha.OperStatus_UNKNOWN,
2584 }); err != nil {
2585 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2586 }
2587 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002588
2589 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002590 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002591 cloned := proto.Clone(device).(*voltha.Device)
2592 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2593 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2594 dh.device = cloned // update local copy of the device
2595 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002596
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002597 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002598 // Stop the Stats collector
2599 if dh.isCollectorActive {
2600 dh.stopCollector <- true
2601 }
2602 // stop the heartbeat check routine
2603 if dh.isHeartbeatCheckActive {
2604 dh.stopHeartbeatCheck <- true
2605 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002606 // Stop the read indication only if it the routine is active
2607 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2608 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2609 // on next execution of the readIndication routine.
2610 if dh.isReadIndicationRoutineActive {
2611 dh.stopIndications <- true
2612 }
2613 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002614 dh.transitionMap.Handle(ctx, DeviceInit)
2615
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302616 }
2617}
kesavand39e0aa32020-01-28 20:58:50 -05002618
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302619func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2620 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2621 if err != nil || device == nil {
2622 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2623 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2624 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2625 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2626 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2627 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2628 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2629 return
2630 }
2631
2632 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2633 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2634 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2635 DeviceId: dh.device.Id,
2636 OperStatus: voltha.OperStatus_REBOOTED,
2637 ConnStatus: voltha.ConnectStatus_REACHABLE,
2638 }); err != nil {
2639 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2640 }
2641
2642 dh.lockDevice.RLock()
2643 // Stop the read indication only if it the routine is active
2644 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2645 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2646 // on next execution of the readIndication routine.
2647 if dh.isReadIndicationRoutineActive {
2648 dh.stopIndications <- true
2649 }
2650 dh.lockDevice.RUnlock()
2651
2652 //raise olt communication failure event
2653 raisedTs := time.Now().Unix()
2654 cloned := proto.Clone(device).(*voltha.Device)
2655 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2656 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2657 dh.device = cloned // update local copy of the device
2658 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2659
2660 dh.cleanupDeviceResources(ctx)
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002661
2662 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302663 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002664 if dh.isCollectorActive {
2665 dh.stopCollector <- true
2666 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302667 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002668 if dh.isHeartbeatCheckActive {
2669 dh.stopHeartbeatCheck <- true
2670 }
2671 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302672
2673 var wg sync.WaitGroup
2674 wg.Add(1) // for the multicast handler routine
2675 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2676 for _, flMgr := range dh.flowMgr {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002677 if flMgr != nil {
2678 wg.Add(1) // for the flow handler routine
2679 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2680 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302681 }
2682 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2683 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2684 } else {
2685 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2686 }
2687
2688 //reset adapter reconcile flag
2689 dh.adapterPreviouslyConnected = false
2690 for {
2691
2692 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2693 if err != nil || childDevices == nil {
2694 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2695 continue
2696 }
2697 if len(childDevices.Items) == 0 {
2698 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
2699 break
2700 } else {
2701 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
2702 time.Sleep(5 * time.Second)
2703 }
2704
2705 }
2706 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
2707 dh.transitionMap.Handle(ctx, DeviceInit)
2708
2709}
2710
kesavand39e0aa32020-01-28 20:58:50 -05002711// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002712func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2713 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2714 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002715}
2716
2717// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002718func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2719 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2720 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002721}
2722
Mahir Gunyela2e68702022-12-07 00:00:42 -08002723// 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 +00002724func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2725 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002726 if port.GetType() == voltha.Port_ETHERNET_NNI {
2727 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002728 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302729 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302730 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002731 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002732 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002733 }
2734 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002735 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002736 ponIntf := &oop.Interface{IntfId: ponID}
2737 var operStatus voltha.OperStatus_Types
2738 if enablePort {
2739 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302740 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002741
2742 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302743 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002744 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002745 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002746 }
2747 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002748 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002749 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002750 } else {
2751 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302752 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002753 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302754 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002755 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002756 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002757 }
2758 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002759 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002760 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002761 }
khenaidoodc2116e2021-10-19 17:33:19 -04002762 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002763 DeviceId: dh.device.Id,
2764 PortType: voltha.Port_PON_OLT,
2765 PortNo: port.PortNo,
2766 OperStatus: operStatus,
2767 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302768 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302769 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002770 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002771 }
2772 return nil
2773}
2774
Mahir Gunyela2e68702022-12-07 00:00:42 -08002775// disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002776func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002777 // Disable the port and update the oper_port_status to core
2778 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002779 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002780 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002781 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302782 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302783 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002784 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002785 }
2786 }
2787 }
2788 return nil
2789}
2790
Mahir Gunyela2e68702022-12-07 00:00:42 -08002791// populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002792func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2793 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2794 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002795 if port.Type == voltha.Port_ETHERNET_NNI {
2796 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002797 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002798 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002799 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002800 }
2801 }
2802 if port.Type == voltha.Port_PON_OLT {
2803 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002804 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002805 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002806 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002807 }
2808 }
2809 }
2810}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002811
2812// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002813func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002814 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07002815 if dh.getDeviceDeletionInProgressFlag() {
2816 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
2817 // will reboot, so everything will be reset on the pOLT too.
2818 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
2819 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
2820 return nil
2821 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002822 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002823 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002824
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002825 var sn *oop.SerialNumber
2826 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002827 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302828 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002829 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302830 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002831 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002832 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002833
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002834 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002835 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00002836 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002837 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2838 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2839 "device-id": dh.device.Id,
2840 "intf-id": intfID,
2841 "onuID": onuID,
2842 "err": err})
2843 } else {
2844 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00002845 // Delete flows from device before schedulers and queue
2846 // Clear flowids for gem cache.
2847 removedFlows := []uint64{}
2848 for _, gem := range onuGem.GemPorts {
2849 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
2850 for _, flowID := range flowIDs {
2851 //multiple gem port can have the same flow id
2852 //it is better to send only one flowRemove request to the agent
2853 var alreadyRemoved bool
2854 for _, removedFlowID := range removedFlows {
2855 if removedFlowID == flowID {
2856 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
2857 alreadyRemoved = true
2858 break
2859 }
2860 }
2861 if !alreadyRemoved {
Mahir Gunyela2e68702022-12-07 00:00:42 -08002862 dh.removeFlowFromDevice(ctx, flowID, intfID)
yasin saplie87d4bd2021-12-06 09:04:03 +00002863 removedFlows = appendUnique64bit(removedFlows, flowID)
2864 }
2865 }
2866 }
2867 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
2868 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002869 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2870 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2871 "device-id": dh.device.Id,
2872 "onu-device": onu,
2873 "err": err})
2874 }
yasin saplibddc2d72022-02-08 13:10:17 +00002875 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002876 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2877 "intf-id": intfID,
2878 "onu-device": onu,
2879 "onu-gem": onuGem,
2880 "err": err})
2881 //Not returning error on cleanup.
2882 }
2883 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302884
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002885 }
yasin saplibddc2d72022-02-08 13:10:17 +00002886 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002887 dh.onus.Delete(onuKey)
2888 dh.discOnus.Delete(onuSn)
2889
2890 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002891 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302892 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302893 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002894 "onu-id": onuID}, err).Log()
2895 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002896
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002897 return nil
2898}
Mahir Gunyela2e68702022-12-07 00:00:42 -08002899func (dh *DeviceHandler) removeFlowFromDevice(ctx context.Context, flowID uint64, intfID uint32) {
2900 flow := &oop.Flow{FlowId: flowID}
2901 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
2902 logger.Warnw(ctx, "failed-to-get-flow-mgr-to-remove-flow-from-device", log.Fields{
2903 "device-id": dh.device.Id})
2904 } else {
2905 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
2906 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
2907 "device-id": dh.device.Id,
2908 "err": err})
2909 }
2910 }
2911}
Girish Gowdracefae192020-03-19 18:14:10 -07002912
2913func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002914 for _, field := range flow_utils.GetOfbFields(flow) {
2915 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002916 return field.GetPort()
2917 }
2918 }
2919 return InvalidPort
2920}
2921
2922func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002923 for _, action := range flow_utils.GetActions(flow) {
2924 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002925 if out := action.GetOutput(); out != nil {
2926 return out.GetPort()
2927 }
2928 }
2929 }
2930 return InvalidPort
2931}
2932
Girish Gowdracefae192020-03-19 18:14:10 -07002933func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2934 inPort := getInPortFromFlow(flow)
2935 outPort := getOutPortFromFlow(flow)
2936
2937 if inPort == InvalidPort || outPort == InvalidPort {
2938 return inPort, outPort
2939 }
2940
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002941 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002942 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002943 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002944 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002945 return uniPort, outPort
2946 }
2947 }
2948 } else {
2949 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002950 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002951 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002952 return inPort, uniPort
2953 }
2954 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002955 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002956 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002957 return uniPort, outPort
2958 }
2959 }
2960 }
2961
2962 return InvalidPort, InvalidPort
2963}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002964
2965func extractOmciTransactionID(omciPkt []byte) uint16 {
2966 if len(omciPkt) > 3 {
2967 d := omciPkt[0:2]
2968 transid := binary.BigEndian.Uint16(d)
2969 return transid
2970 }
2971 return 0
2972}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002973
2974// StoreOnuDevice stores the onu parameters to the local cache.
2975func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2976 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2977 dh.onus.Store(onuKey, onuDevice)
2978}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002979
khenaidoodc2116e2021-10-19 17:33:19 -04002980func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002981 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002982 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002983 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002984 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002985 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002986 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002987 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002988 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2989 return nil, err
2990 }
2991 ID = device.ProxyAddress.GetOnuId()
2992 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2993 valueparam.Onu = &Onu
2994 valueparam.Value = value
2995
2996 // This API is unsupported until agent patch is added
2997 resp.Unsupported = uint32(value)
2998 _ = ctx
2999
3000 // Uncomment this code once agent changes are complete and tests
3001 /*
3002 resp, err = dh.Client.GetValue(ctx, valueparam)
3003 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003004 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08003005 return nil, err
3006 }
3007 */
3008
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003009 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 -08003010 return resp, nil
3011}
Girish Gowdra9602eb42020-09-09 15:50:39 -07003012
yasin saplid0566272021-12-21 09:10:30 +00003013func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
3014 // Default to NNI
3015 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07003016 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003017 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003018 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003019 }
3020 return intfID
3021}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003022
Mahir Gunyelb0046752021-02-26 13:51:05 -08003023func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
3024 dh.perPonOnuIndicationChannelLock.Lock()
3025 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
3026 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003027 return ch.indicationChannel
3028 }
3029 channels := onuIndicationChannels{
3030 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08003031 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003032 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08003033 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003034 stopChannel: make(chan struct{}),
3035 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003036 dh.perPonOnuIndicationChannel[intfID] = channels
3037 dh.perPonOnuIndicationChannelLock.Unlock()
3038 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003039 return channels.indicationChannel
3040
3041}
3042
Mahir Gunyelb0046752021-02-26 13:51:05 -08003043func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
3044 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3045 dh.perPonOnuIndicationChannelLock.Lock()
3046 defer dh.perPonOnuIndicationChannelLock.Unlock()
3047 for _, v := range dh.perPonOnuIndicationChannel {
3048 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003049 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003050 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003051}
3052
Mahir Gunyelb0046752021-02-26 13:51:05 -08003053func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3054 ind := onuIndicationMsg{
3055 ctx: ctx,
3056 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003057 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003058 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003059 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003060 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003061}
3062
Mahir Gunyelb0046752021-02-26 13:51:05 -08003063func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003064 for {
3065 select {
3066 // process one indication per onu, before proceeding to the next one
3067 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003068 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003069 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003070 "ind": indication})
3071 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003072 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003073 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003074 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3075 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003076 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003077 }
3078 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003079 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003080 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3081 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003082 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003083 }
3084 }
3085 case <-onuChannels.stopChannel:
3086 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3087 close(onuChannels.indicationChannel)
3088 return
3089 }
3090 }
3091}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003092
3093// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3094// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003095func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003096 if dh.getDeviceDeletionInProgressFlag() {
3097 // The device itself is going to be reset as part of deletion. So nothing to be done.
3098 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3099 return nil
3100 }
3101
Girish Gowdra491a9c62021-01-06 16:43:07 -08003102 // Step1 : Fill McastFlowOrGroupControlBlock
3103 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3104 // Step3 : Wait on response channel for response
3105 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003106 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003107 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3108 errChan := make(chan error)
3109 var groupID uint32
3110 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3111 ctx: ctx,
3112 flowOrGroupAction: action,
3113 flow: flow,
3114 group: group,
3115 errChan: &errChan,
3116 }
3117 if flow != nil {
3118 groupID = flow_utils.GetGroup(flow)
3119 } else if group != nil {
3120 groupID = group.Desc.GroupId
3121 } else {
3122 return errors.New("flow-and-group-both-nil")
3123 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003124 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3125 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3126 // Derive the appropriate go routine to handle the request by a simple module operation.
3127 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3128 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3129 // Wait for handler to return error value
3130 err := <-errChan
3131 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3132 return err
3133 }
3134 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3135 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003136}
3137
3138// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003139func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003140 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003141 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003142 // block on the channel to receive an incoming mcast flow/group
3143 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003144 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3145 if mcastFlowOrGroupCb.flow != nil {
3146 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3147 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3148 log.Fields{"device-id": dh.device.Id,
3149 "flowToAdd": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003150 err := olterrors.NewErrNotFound("no-flow-manager-found-to-add-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3151 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3152 for _, flMgr := range dh.flowMgr {
3153 if flMgr != nil {
3154 err = flMgr.AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3155 break
3156 }
3157 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003158 // Pass the return value over the return channel
3159 *mcastFlowOrGroupCb.errChan <- err
3160 } else { // flow remove
3161 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3162 log.Fields{"device-id": dh.device.Id,
3163 "flowToRemove": mcastFlowOrGroupCb.flow})
Mahir Gunyela2e68702022-12-07 00:00:42 -08003164 // The mcast flow is not unique to any particular PON port, so it is OK to default to first non nil PON
3165 err := olterrors.NewErrNotFound("no-flow-manager-found-to-remove-mcast-flow", log.Fields{"device-id": dh.device.Id}, nil).(error)
3166 for _, flMgr := range dh.flowMgr {
3167 if flMgr != nil {
3168 err = flMgr.RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3169 break
3170 }
3171 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003172 // Pass the return value over the return channel
3173 *mcastFlowOrGroupCb.errChan <- err
3174 }
3175 } else { // mcast group
3176 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3177 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3178 log.Fields{"device-id": dh.device.Id,
3179 "groupToAdd": mcastFlowOrGroupCb.group})
3180 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3181 // Pass the return value over the return channel
3182 *mcastFlowOrGroupCb.errChan <- err
3183 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3184 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3185 log.Fields{"device-id": dh.device.Id,
3186 "groupToModify": mcastFlowOrGroupCb.group})
3187 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3188 // Pass the return value over the return channel
3189 *mcastFlowOrGroupCb.errChan <- err
3190 } else { // group remove
3191 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3192 log.Fields{"device-id": dh.device.Id,
3193 "groupToRemove": mcastFlowOrGroupCb.group})
3194 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3195 // Pass the return value over the return channel
3196 *mcastFlowOrGroupCb.errChan <- err
3197 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003198 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003199 case <-stopHandler:
3200 dh.mcastHandlerRoutineActive[routineIndex] = false
3201 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003202 }
3203 }
3204}
kesavand62126212021-01-12 04:56:06 -05003205
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003206// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003207func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003208 for i, v := range dh.stopMcastHandlerRoutine {
3209 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003210 select {
3211 case v <- true:
3212 case <-time.After(time.Second * 5):
3213 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3214 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003215 }
3216 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003217 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003218 logger.Debug(ctx, "stopped all mcast handler routines")
3219}
3220
kesavand62126212021-01-12 04:56:06 -05003221func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3222
3223 singleValResp := extension.SingleGetValueResponse{
3224 Response: &extension.GetValueResponse{
3225 Response: &extension.GetValueResponse_PortCoutners{
3226 PortCoutners: &extension.GetOltPortCountersResponse{},
3227 },
3228 },
3229 }
3230
3231 errResp := func(status extension.GetValueResponse_Status,
3232 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3233 return &extension.SingleGetValueResponse{
3234 Response: &extension.GetValueResponse{
3235 Status: status,
3236 ErrReason: reason,
3237 },
3238 }
3239 }
3240
3241 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3242 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3243 //send error response
3244 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3245 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3246 }
3247 statIndChn := make(chan bool, 1)
3248 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3249 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3250 //request openOlt agent to send the the port statistics indication
3251
3252 go func() {
3253 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3254 if err != nil {
3255 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3256 }
3257 }()
3258 select {
3259 case <-statIndChn:
3260 //indication received for ports stats
3261 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3262 case <-time.After(oltPortInfoTimeout * time.Second):
3263 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3264 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3265 case <-ctx.Done():
3266 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3267 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3268 }
3269 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3270 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003271 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003272 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3273 cmnni := dh.portStats.collectNNIMetrics(intfID)
3274 if cmnni == nil {
3275 //TODO define the error reason
3276 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3277 }
3278 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3279 return &singleValResp
3280
3281 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3282 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003283 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003284 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3285 cmpon := dh.portStats.collectPONMetrics(intfID)
3286 if cmpon == nil {
3287 //TODO define the error reason
3288 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3289 }
3290 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3291 return &singleValResp
3292 }
3293 }
3294 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3295}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303296
3297func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3298
3299 singleValResp := extension.SingleGetValueResponse{
3300 Response: &extension.GetValueResponse{
3301 Response: &extension.GetValueResponse_OnuPonCounters{
3302 OnuPonCounters: &extension.GetOnuCountersResponse{},
3303 },
3304 },
3305 }
3306
3307 errResp := func(status extension.GetValueResponse_Status,
3308 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3309 return &extension.SingleGetValueResponse{
3310 Response: &extension.GetValueResponse{
3311 Status: status,
3312 ErrReason: reason,
3313 },
3314 }
3315 }
3316 intfID := onuPonInfo.IntfId
3317 onuID := onuPonInfo.OnuId
3318 onuKey := dh.formOnuKey(intfID, onuID)
3319
3320 if _, ok := dh.onus.Load(onuKey); !ok {
3321 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3322 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3323 }
3324 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3325 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3326 if cmnni == nil {
3327 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3328 }
3329 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3330 return &singleValResp
3331
3332}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003333
3334func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3335
3336 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3337 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3338 if err != nil {
3339 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3340 return generateSingleGetValueErrorResponse(err)
3341 }
3342 return &extension.SingleGetValueResponse{
3343 Response: &extension.GetValueResponse{
3344 Status: extension.GetValueResponse_OK,
3345 Response: &extension.GetValueResponse_RxPower{
3346 RxPower: &extension.GetRxPowerResponse{
3347 IntfId: rxPowerRequest.IntfId,
3348 OnuId: rxPowerRequest.OnuId,
3349 Status: rxPower.Status,
3350 FailReason: rxPower.FailReason.String(),
3351 RxPower: rxPower.RxPowerMeanDbm,
3352 },
3353 },
3354 },
3355 }
3356}
3357
3358func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3359 errResp := func(status extension.GetValueResponse_Status,
3360 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3361 return &extension.SingleGetValueResponse{
3362 Response: &extension.GetValueResponse{
3363 Status: status,
3364 ErrReason: reason,
3365 },
3366 }
3367 }
3368
3369 if err != nil {
3370 if e, ok := status.FromError(err); ok {
3371 switch e.Code() {
3372 case codes.Internal:
3373 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3374 case codes.DeadlineExceeded:
3375 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3376 case codes.Unimplemented:
3377 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3378 case codes.NotFound:
3379 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3380 }
3381 }
3382 }
3383
3384 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3385}
khenaidoo106c61a2021-08-11 18:05:46 -04003386
3387/*
3388Helper functions to communicate with Core
3389*/
3390
3391func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3392 cClient, err := dh.coreClient.GetCoreServiceClient()
3393 if err != nil || cClient == nil {
3394 return nil, err
3395 }
3396 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3397 defer cancel()
3398 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3399}
3400
khenaidoodc2116e2021-10-19 17:33:19 -04003401func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003402 cClient, err := dh.coreClient.GetCoreServiceClient()
3403 if err != nil || cClient == nil {
3404 return nil, err
3405 }
3406 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3407 defer cancel()
3408 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3409}
3410
khenaidoodc2116e2021-10-19 17:33:19 -04003411func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003412 cClient, err := dh.coreClient.GetCoreServiceClient()
3413 if err != nil || cClient == nil {
3414 return err
3415 }
3416 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3417 defer cancel()
3418 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3419 return err
3420}
3421
3422func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3423 cClient, err := dh.coreClient.GetCoreServiceClient()
3424 if err != nil || cClient == nil {
3425 return nil, err
3426 }
3427 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3428 defer cancel()
3429 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3430}
3431
3432func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3433 cClient, err := dh.coreClient.GetCoreServiceClient()
3434 if err != nil || cClient == nil {
3435 return nil, err
3436 }
3437 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3438 defer cancel()
3439 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3440}
3441
3442func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3443 cClient, err := dh.coreClient.GetCoreServiceClient()
3444 if err != nil || cClient == nil {
3445 return err
3446 }
3447 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3448 defer cancel()
3449 _, err = cClient.DeviceUpdate(subCtx, device)
3450 return err
3451}
3452
khenaidoodc2116e2021-10-19 17:33:19 -04003453func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003454 cClient, err := dh.coreClient.GetCoreServiceClient()
3455 if err != nil || cClient == nil {
3456 return nil, err
3457 }
3458 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3459 defer cancel()
3460 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3461}
3462
khenaidoodc2116e2021-10-19 17:33:19 -04003463func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003464 cClient, err := dh.coreClient.GetCoreServiceClient()
3465 if err != nil || cClient == nil {
3466 return err
3467 }
3468 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3469 defer cancel()
3470 _, err = cClient.SendPacketIn(subCtx, pkt)
3471 return err
3472}
3473
3474func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3475 cClient, err := dh.coreClient.GetCoreServiceClient()
3476 if err != nil || cClient == nil {
3477 return err
3478 }
3479 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3480 defer cancel()
3481 _, err = cClient.PortCreated(subCtx, port)
3482 return err
3483}
3484
khenaidoodc2116e2021-10-19 17:33:19 -04003485func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003486 cClient, err := dh.coreClient.GetCoreServiceClient()
3487 if err != nil || cClient == nil {
3488 return err
3489 }
3490 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3491 defer cancel()
3492 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3493 return err
3494}
3495
khenaidoodc2116e2021-10-19 17:33:19 -04003496func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003497 cClient, err := dh.coreClient.GetCoreServiceClient()
3498 if err != nil || cClient == nil {
3499 return err
3500 }
3501 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3502 defer cancel()
3503 _, err = cClient.PortStateUpdate(subCtx, portState)
3504 return err
3505}
3506
khenaidoodc2116e2021-10-19 17:33:19 -04003507func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003508 cClient, err := dh.coreClient.GetCoreServiceClient()
3509 if err != nil || cClient == nil {
3510 return nil, err
3511 }
3512 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3513 defer cancel()
3514 return cClient.GetDevicePort(subCtx, portFilter)
3515}
3516
3517/*
3518Helper functions to communicate with child adapter
3519*/
3520
khenaidoodc2116e2021-10-19 17:33:19 -04003521func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003522 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3523 if err != nil || aClient == nil {
3524 return err
3525 }
3526 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3527 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3528 defer cancel()
3529 _, err = aClient.OmciIndication(subCtx, response)
3530 return err
3531}
3532
khenaidoodc2116e2021-10-19 17:33:19 -04003533func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003534 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3535 if err != nil || aClient == nil {
3536 return err
3537 }
3538 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3539 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3540 defer cancel()
3541 _, err = aClient.OnuIndication(subCtx, onuInd)
3542 return err
3543}
3544
khenaidoodc2116e2021-10-19 17:33:19 -04003545func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003546 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3547 if err != nil || aClient == nil {
3548 return err
3549 }
3550 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3551 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3552 defer cancel()
3553 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3554 return err
3555}
3556
khenaidoodc2116e2021-10-19 17:33:19 -04003557func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003558 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3559 if err != nil || aClient == nil {
3560 return err
3561 }
3562 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3563 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3564 defer cancel()
3565 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3566 return err
3567}
3568
khenaidoodc2116e2021-10-19 17:33:19 -04003569func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003570 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3571 if err != nil || aClient == nil {
3572 return err
3573 }
3574 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3575 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3576 defer cancel()
3577 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3578 return err
3579}
3580
3581/*
3582Helper functions for remote communication
3583*/
3584
3585// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3586// supports is deleted
3587func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3588 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3589
3590 dh.lockChildAdapterClients.Lock()
3591 defer dh.lockChildAdapterClients.Unlock()
3592 if _, ok := dh.childAdapterClients[endpoint]; ok {
3593 // Already set
3594 return nil
3595 }
3596
3597 // Setup child's adapter grpc connection
3598 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003599 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3600 dh.cfg.AdapterEndpoint,
3601 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05003602 "onu_inter_adapter_service.OnuInterAdapterService",
3603 dh.onuInterAdapterRestarted,
3604 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003605 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3606 return err
3607 }
khenaidooefff76e2021-12-15 16:51:30 -05003608 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003609
3610 // Wait until we have a connection to the child adapter.
3611 // Unlimited retries or until context expires
3612 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3613 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3614 for {
3615 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3616 if err == nil && client != nil {
3617 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3618 break
3619 }
3620 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3621 // Backoff
3622 if err = backoff.Backoff(subCtx); err != nil {
3623 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3624 break
3625 }
3626 }
3627 return nil
3628}
3629
khenaidoodc2116e2021-10-19 17:33:19 -04003630func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003631
3632 // First check from cache
3633 dh.lockChildAdapterClients.RLock()
3634 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3635 dh.lockChildAdapterClients.RUnlock()
3636 return cgClient.GetOnuInterAdapterServiceClient()
3637 }
3638 dh.lockChildAdapterClients.RUnlock()
3639
3640 // Set the child connection - can occur on restarts
3641 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3642 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3643 cancel()
3644 if err != nil {
3645 return nil, err
3646 }
3647
3648 // Get the child client now
3649 dh.lockChildAdapterClients.RLock()
3650 defer dh.lockChildAdapterClients.RUnlock()
3651 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3652 return cgClient.GetOnuInterAdapterServiceClient()
3653 }
3654 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3655}
3656
3657func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3658 dh.lockChildAdapterClients.Lock()
3659 defer dh.lockChildAdapterClients.Unlock()
3660 for key, client := range dh.childAdapterClients {
3661 client.Stop(ctx)
3662 delete(dh.childAdapterClients, key)
3663 }
3664}
3665
khenaidooefff76e2021-12-15 16:51:30 -05003666// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
3667func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
3668 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003669 return nil
3670}
3671
khenaidooefff76e2021-12-15 16:51:30 -05003672// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
3673func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
3674 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003675 return nil
3676 }
khenaidooefff76e2021-12-15 16:51:30 -05003677 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04003678}
Girish Gowdra950326e2021-11-05 12:43:24 -07003679
3680func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3681 dh.lockDevice.Lock()
3682 defer dh.lockDevice.Unlock()
3683 dh.isDeviceDeletionInProgress = flag
3684}
3685
3686func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3687 dh.lockDevice.RLock()
3688 defer dh.lockDevice.RUnlock()
3689 return dh.isDeviceDeletionInProgress
3690}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003691
3692// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3693// Returns false if waiting timed out.
3694func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3695 c := make(chan struct{})
3696 go func() {
3697 defer close(c)
3698 wg.Wait()
3699 }()
3700 select {
3701 case <-c:
3702 return true // completed normally
3703 case <-time.After(timeout):
3704 return false // timed out
3705 }
3706}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303707
3708func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
3709 val, err := json.Marshal(signature)
3710 if err != nil {
3711 logger.Error(ctx, "failed-to-marshal")
3712 return
3713 }
3714 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
3715 logger.Error(ctx, "failed-to-store-hearbeat-signature")
3716 }
3717}
3718
3719func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
3720 var signature uint32
3721
3722 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
3723 if er == nil {
3724 if Value != nil {
3725 Val, er := kvstore.ToByte(Value.Value)
3726 if er != nil {
3727 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
3728 return signature
3729 }
3730 if er = json.Unmarshal(Val, &signature); er != nil {
3731 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
3732 return signature
3733 }
3734 }
3735 }
3736 return signature
3737}