blob: e8ced1e27c78ec971457237493560149ea30e558 [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053024 "encoding/json"
Girish Gowdra491a9c62021-01-06 16:43:07 -080025 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "fmt"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
Elia Battiston599d25f2022-02-16 14:49:08 +010033 "github.com/opencord/voltha-lib-go/v7/pkg/db"
34 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
35
khenaidoo106c61a2021-08-11 18:05:46 -040036 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040037
Matteo Scandolo945e4012019-12-12 14:16:11 -080038 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070039 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000040 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
41 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040042 "github.com/opencord/voltha-lib-go/v7/pkg/config"
43 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
44 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
45 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070046 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040047 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080048
khenaidoo106c61a2021-08-11 18:05:46 -040049 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053050 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080051 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040052 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040053 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040054 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040055 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
56 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040057 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
58 oop "github.com/opencord/voltha-protos/v5/go/openolt"
59 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070060 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040061 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040062 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053063)
64
salmansiddiqui7ac62132019-08-22 03:58:50 +000065// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040066const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080067 InvalidPort = 0xffffffff
68 MaxNumOfGroupHandlerChannels = 256
69
70 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
71 McastFlowOrGroupModify = "McastFlowOrGroupModify"
72 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050073 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010074
75 defaultPortSpeedMbps = 1000
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053076 heartbeatPath = "heartbeat"
Manikkaraj kb1d51442019-07-23 10:41:02 -040077)
78
Phaneendra Manda4c62c802019-03-06 21:37:49 +053079//DeviceHandler will interact with the OLT device.
80type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040081 cm *config.ConfigManager
82 device *voltha.Device
83 cfg *conf.AdapterFlags
84 coreClient *vgrpc.Client
85 childAdapterClients map[string]*vgrpc.Client
86 lockChildAdapterClients sync.RWMutex
87 EventProxy eventif.EventProxy
88 openOLT *OpenOLT
khenaidooefff76e2021-12-15 16:51:30 -050089 exitChannel chan struct{}
khenaidoo106c61a2021-08-11 18:05:46 -040090 lockDevice sync.RWMutex
91 Client oop.OpenoltClient
92 transitionMap *TransitionMap
93 clientCon *grpc.ClientConn
94 flowMgr []*OpenOltFlowMgr
95 groupMgr *OpenOltGroupMgr
96 eventMgr *OpenOltEventMgr
97 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +053098 kvStore *db.Backend // backend kv store connection handle
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070099
100 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530101
Matteo Scandolo7eaec532022-06-23 15:54:57 -0700102 // discOnus (map[onuSn]bool) contains a list of ONUs that have been discovered, indexed by ONU SerialNumber.
103 // if the value is true that means the OnuDiscovery indication
104 // is currently being processed and thus we can ignore concurrent requests
105 // if it's false it means the processing has completed and we shouldn't be receiving a new indication
106 // if we do it means something went wrong and we need to retry
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700107 discOnus sync.Map
108 onus sync.Map
109 portStats *OpenOltStatisticsMgr
110 metrics *pmmetrics.PmMetrics
111 stopCollector chan bool
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
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700136//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
Girish Gowdra491a9c62021-01-06 16:43:07 -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)
163type 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 Gunyela3f9add2019-06-06 15:13:19 -0700182//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
196//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
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700357//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 {
1003 return olterrors.ErrFlowManagerInstantiating
1004 }
Girish Gowdra76a1b092021-07-28 10:07:04 -07001005 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001006 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001007 /* TODO: Instantiate Alarm , stats , BW managers */
1008 /* Instantiating Event Manager to handle Alarms and KPIs */
1009 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1010
1011 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001012 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001013
1014 return nil
1015
1016}
1017
Neha Sharma96b7bf22020-06-15 10:37:32 +00001018func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001019 var err error
1020 var deviceInfo *oop.DeviceInfo
1021
Neha Sharma8f4e4322020-08-06 10:51:53 +00001022 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001023
1024 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001025 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001026 }
1027 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001028 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001029 }
1030
Neha Sharma96b7bf22020-06-15 10:37:32 +00001031 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001032 dh.device.Root = true
1033 dh.device.Vendor = deviceInfo.Vendor
1034 dh.device.Model = deviceInfo.Model
1035 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1036 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1037 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1038
1039 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001040 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001041 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001042 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001043 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001044 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001045 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001046 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001047 dh.device.MacAddress = genmac
1048 } else {
1049 dh.device.MacAddress = deviceInfo.DeviceId
1050 }
1051
1052 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001053 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001054 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001055 }
1056
1057 return deviceInfo, nil
1058}
1059
Neha Sharma96b7bf22020-06-15 10:37:32 +00001060func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001061 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00001062
1063 defer func() {
1064 dh.lockDevice.Lock()
1065 dh.isCollectorActive = false
1066 dh.lockDevice.Unlock()
1067 }()
1068
1069 dh.lockDevice.Lock()
1070 dh.isCollectorActive = true
1071 dh.lockDevice.Unlock()
1072
Naga Manjunath7615e552019-10-11 22:35:47 +05301073 for {
1074 select {
1075 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001076 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301077 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001078 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001079
khenaidoo106c61a2021-08-11 18:05:46 -04001080 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001081 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001082 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001083 continue
1084 }
khenaidoo106c61a2021-08-11 18:05:46 -04001085 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301086 // NNI Stats
1087 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001088 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301089 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001090 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001091 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301093 }
1094 // PON Stats
1095 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001096 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301097 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1098 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001099 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001100 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301101 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001102 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001103
yasin sapli9e4c5092022-02-01 13:52:33 +00001104 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001105 if len(onuGemInfoLst) > 0 {
1106 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001107 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001108 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301109 }
1110 }
1111 }
1112}
1113
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001114//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301115func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001116 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001117 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301118 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301119
1120 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001121 cgClient, err := dh.coreClient.GetCoreServiceClient()
1122 if err != nil {
1123 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1124 return
1125 }
1126
1127 // Now, set the initial PM configuration for that device
1128 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001129 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301130 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301131}
1132
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001134func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1135 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001136 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301137 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001138 HwDesc: "open_pon",
1139 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001140 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001141 },
1142 SwitchFeatures: &of.OfpSwitchFeatures{
1143 NBuffers: 256,
1144 NTables: 2,
1145 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1146 of.OfpCapabilities_OFPC_TABLE_STATS |
1147 of.OfpCapabilities_OFPC_PORT_STATS |
1148 of.OfpCapabilities_OFPC_GROUP_STATS),
1149 },
1150 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301151}
1152
khenaidoo106c61a2021-08-11 18:05:46 -04001153// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001154func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001155 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001156 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001157 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001158 }
khenaidoo106c61a2021-08-11 18:05:46 -04001159 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001160}
1161
Neha Sharma96b7bf22020-06-15 10:37:32 +00001162func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001163 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 -07001164 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001165 var deviceID string
1166 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001167 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001168
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001169 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001170 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001171 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 -07001172 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1173 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001174
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001175 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301176
1177 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1178
Neha Sharma96b7bf22020-06-15 10:37:32 +00001179 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 -07001180 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001181
khenaidoodc2116e2021-10-19 17:33:19 -04001182 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001183 ParentId: dh.device.Id,
1184 OnuId: omciInd.OnuId,
1185 ParentPortNo: ponPort,
1186 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001187 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301188 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001189 "intf-id": omciInd.IntfId,
1190 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001191 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001192 deviceType = onuDevice.Type
1193 deviceID = onuDevice.Id
1194 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001195 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001196 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001197 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001198 } else {
1199 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001200 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 +05301201 deviceType = onuInCache.(*OnuDevice).deviceType
1202 deviceID = onuInCache.(*OnuDevice).deviceID
1203 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001204 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001205 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001206
khenaidoodc2116e2021-10-19 17:33:19 -04001207 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001208 ParentDeviceId: proxyDeviceID,
1209 ChildDeviceId: deviceID,
1210 Message: omciInd.Pkt,
1211 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301212 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001213 "source": dh.openOLT.config.AdapterEndpoint,
1214 "device-type": deviceType,
1215 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001216 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001217 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001218 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001219 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301220}
1221
khenaidoo106c61a2021-08-11 18:05:46 -04001222// //ProcessInterAdapterMessage sends the proxied messages to the target device
1223// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1224// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001225// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001226// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001227// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001228// return dh.handleInterAdapterOmciMsg(ctx, msg)
1229// }
1230// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1231// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001232
kesavandb9f54fd2021-11-25 20:08:04 +05301233// ProxyOmciRequests sends the proxied OMCI message to the target device
1234func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301235 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1236 return status.Error(codes.Unavailable, "OLT unreachable")
1237 }
kesavandb9f54fd2021-11-25 20:08:04 +05301238 if omciMsgs.GetProxyAddress() == nil {
1239 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1240 if err != nil {
1241 return olterrors.NewErrNotFound("onu", log.Fields{
1242 "parent-device-id": dh.device.Id,
1243 "child-device-id": omciMsgs.ChildDeviceId}, err)
1244 }
1245 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1246 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1247 return olterrors.NewErrCommunication("send-failed", log.Fields{
1248 "parent-device-id": dh.device.Id,
1249 "child-device-id": omciMsgs.ChildDeviceId}, err)
1250 }
1251 } else {
1252 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1253 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1254 return olterrors.NewErrCommunication("send-failed", log.Fields{
1255 "parent-device-id": dh.device.Id,
1256 "child-device-id": omciMsgs.ChildDeviceId}, err)
1257 }
1258 }
1259 return nil
1260}
1261
1262func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1263 var intfID uint32
1264 var onuID uint32
1265 var connectStatus common.ConnectStatus_Types
1266 if onuDevice != nil {
1267 intfID = onuDevice.ProxyAddress.GetChannelId()
1268 onuID = onuDevice.ProxyAddress.GetOnuId()
1269 connectStatus = onuDevice.ConnectStatus
1270 } else {
1271 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1272 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1273 connectStatus = omciMsgs.GetConnectStatus()
1274 }
1275 if connectStatus != voltha.ConnectStatus_REACHABLE {
1276 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1277
1278 return olterrors.NewErrCommunication("unreachable", log.Fields{
1279 "intf-id": intfID,
1280 "onu-id": onuID}, nil)
1281 }
1282
1283 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1284 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1285
1286 onuSecOmciMsgList := omciMsgs.GetMessages()
1287
1288 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1289
1290 var omciMessage *oop.OmciMsg
1291 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1292 hex.Encode(hexPkt, onuSecOmciMsg)
1293 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1294
1295 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1296 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1297 //https://jira.opencord.org/browse/VOL-4604
1298 transid := extractOmciTransactionID(onuSecOmciMsg)
1299 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1300 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1301
1302 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1303 if err != nil {
1304 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1305 "intf-id": intfID,
1306 "onu-id": onuID,
1307 "message": omciMessage}, err)
1308 }
1309 }
1310 return nil
1311}
1312
khenaidoo106c61a2021-08-11 18:05:46 -04001313// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001314func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001315 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 -07001316
Abhilash Laxmeshwar092e6ca2022-12-08 19:51:27 +05301317 if DeviceState(dh.device.ConnectStatus) != DeviceState(voltha.ConnectStatus_REACHABLE) {
1318 return status.Error(codes.Unavailable, "OLT unreachable")
1319 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001320 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001321 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001322 if err != nil {
1323 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001324 "parent-device-id": dh.device.Id,
1325 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001326 }
khenaidoo106c61a2021-08-11 18:05:46 -04001327 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1328 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001329 return olterrors.NewErrCommunication("send-failed", 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 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001333 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001334 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1335 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001336 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001337 "parent-device-id": dh.device.Id,
1338 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001339 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001340 }
1341 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301342}
1343
khenaidoodc2116e2021-10-19 17:33:19 -04001344func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 var intfID uint32
1346 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001347 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001348 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001349 intfID = onuDevice.ProxyAddress.GetChannelId()
1350 onuID = onuDevice.ProxyAddress.GetOnuId()
1351 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001352 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001353 intfID = omciMsg.GetProxyAddress().GetChannelId()
1354 onuID = omciMsg.GetProxyAddress().GetOnuId()
1355 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001356 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001357 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001358 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 -08001359
Thomas Lee S94109f12020-03-03 16:39:29 +05301360 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001361 "intf-id": intfID,
1362 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001363 }
1364
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001365 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1366 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301367 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001368 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001369 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1370 hex.Encode(hexPkt, omciMsg.Message)
1371 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1372
1373 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1374 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1375 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001376 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001377 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001378
Neha Sharma8f4e4322020-08-06 10:51:53 +00001379 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001380 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301381 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001382 "intf-id": intfID,
1383 "onu-id": onuID,
1384 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001385 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001386 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001387}
1388
David K. Bainbridge794735f2020-02-11 21:01:37 -08001389func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301390 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 +00001391 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001392 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001393 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001394 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301395 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301396 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001397 st, _ := status.FromError(err)
1398 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001399 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1400
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001401 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301402 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001403 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001404 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001405 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001406 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001407 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001408}
1409
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301410//getChildDevice function can be used in general to get child device, if not found in cache the function will
1411//get from core and update the cache and return the child device.
1412func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1413 var InCacheOnuDev *OnuDevice
1414 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1415 if onuInCache.(*OnuDevice).serialNumber == sn {
1416 InCacheOnuDev = onuInCache.(*OnuDevice)
1417 return false
1418 }
1419 return true
1420 })
1421 //Got the onu device from cache return
1422 if InCacheOnuDev != nil {
1423 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1424 return InCacheOnuDev
1425 }
1426 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1427 ParentId: dh.device.Id,
1428 SerialNumber: sn,
1429 ParentPortNo: parentPortNo,
1430 })
1431 //No device found in core return nil
1432 if onuDevice == nil {
1433 return nil
1434 }
1435 onuID := onuDevice.ProxyAddress.OnuId
1436 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1437 onuKey := dh.formOnuKey(intfID, onuID)
1438
1439 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1440 dh.onus.Store(onuKey, onuDev)
1441 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1442 return onuDev
1443}
1444
1445func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001446 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001447 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301448 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001449
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301450 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1451 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1452 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1453 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1454 if onuDev != nil {
1455 var onuGemInfo *rsrcMgr.OnuGemInfo
1456 var err error
1457 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1458 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1459 return false, err
1460 }
1461 if onuGemInfo != nil {
1462 for _, uni := range onuGemInfo.UniPorts {
1463 uniID := plt.UniIDFromPortNum(uni)
1464 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1465 if len(tpIDs) != 0 {
1466 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1467 tpInstExists = true
1468 break
1469 }
1470 }
1471 }
1472 }
1473 return tpInstExists, nil
1474 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301475
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301476 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1477 ParentId: dh.device.Id,
1478 SerialNumber: sn,
1479 ParentPortNo: parentPortNo,
1480 })
1481 if onuDevice != nil {
1482 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1483 return true, nil
1484 }
1485 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1486
1487 return false, nil
1488
1489}
1490
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001491// processDiscONULOSClear clears the LOS Alarm if it's needed
1492func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301493 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001494 raisedTs := time.Now().Unix()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301495
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001496 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1497 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1498 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1499 OnuLosRaise event sent for it */
1500 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1501 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1502 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
1503 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
1504 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1505 "currentIntfId": onuDiscInd.GetIntfId()})
1506 // TODO:: Should we need to ignore raising OnuLosClear event
1507 // when onu connected to different PON?
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301508 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001509 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1510 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1511 alarmInd.LosStatus = statusCheckOff
1512 go func() {
1513 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1514 logger.Errorw(ctx, "indication-failed", log.Fields{"err": err})
1515 }
1516 }()
1517 // stop iterating
1518 return false
1519 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301520 return true
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001521 })
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301522}
1523
1524func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
1525 channelID := onuDiscInd.GetIntfId()
1526 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1527
1528 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
1529 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1530
1531 tpInstExists, errtp := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1532 if errtp != nil {
1533 return errtp
1534 }
1535 if tpInstExists {
1536 //ignore the discovery if tpinstance is present.
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001537 logger.Debugw(ctx, "ignoring-onu-indication-as-tp-already-exists", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001538 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001539 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001540 inProcess, existing := dh.discOnus.LoadOrStore(sn, true)
1541
1542 // if the ONU existed, handle the LOS Alarm
1543 if existing {
1544
1545 if inProcess.(bool) {
1546 // if we're currently processing the ONU on a different thread, do nothing
1547 logger.Warnw(ctx, "onu-sn-is-being-processed", log.Fields{"sn": sn})
1548 return nil
1549 }
1550 // if we had dealt with this ONU before, but the process didn't complete (this happens in case of errors)
1551 // then continue processing it
1552 logger.Debugw(ctx, "onu-processing-had-completed-but-new-indication", log.Fields{"sn": sn})
1553
1554 dh.processDiscONULOSClear(ctx, onuDiscInd, sn)
serkantule333d152022-10-12 01:44:00 +03001555 return nil
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301556 }
Matteo Scandolo7eaec532022-06-23 15:54:57 -07001557
1558 defer func() {
1559 // once the function completes set the value to false so that
1560 // we know the processing has inProcess.
1561 // Note that this is done after checking if we are already processing
1562 // to avoid changing the value from a different thread
1563 logger.Infow(ctx, "onu-processing-completed", log.Fields{"sn": sn})
1564 dh.discOnus.Store(sn, false)
1565 }()
1566
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001567 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001568
1569 // check the ONU is already know to the OLT
1570 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001571 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001572 ParentId: dh.device.Id,
1573 SerialNumber: sn,
1574 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001575
1576 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001577 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 -08001578 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001579 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 -08001580 switch e.Code() {
1581 case codes.Internal:
1582 // this probably means NOT FOUND, so just create a new device
1583 onuDevice = nil
1584 case codes.DeadlineExceeded:
1585 // if the call times out, cleanup and exit
1586 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001587 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001588 }
1589 }
1590 }
1591
1592 if onuDevice == nil {
1593 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001595 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001596 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001597 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001598
Neha Sharma96b7bf22020-06-15 10:37:32 +00001599 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001600
1601 if err != nil {
1602 // if we can't create an ID in resource manager,
1603 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001604 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001605 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001606 "pon-intf-id": ponintfid,
1607 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001608 }
1609
khenaidoodc2116e2021-10-19 17:33:19 -04001610 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001611 ParentId: dh.device.Id,
1612 ParentPortNo: parentPortNo,
1613 ChannelId: channelID,
1614 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1615 SerialNumber: sn,
1616 OnuId: onuID,
1617 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001618 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001619 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 +05301620 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001621 "pon-intf-id": ponintfid,
1622 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001623 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001624 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 -07001625 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001626 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001627 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301628 log.Fields{"onuDevice": onuDevice,
1629 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001630 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301631 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001632 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001633
khenaidoo106c61a2021-08-11 18:05:46 -04001634 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1635 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1636 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1637 cancel()
1638 if err != nil {
1639 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1640 }
1641
Matteo Scandolo945e4012019-12-12 14:16:11 -08001642 // we can now use the existing ONU Id
1643 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001644 //Insert the ONU into cache to use in OnuIndication.
1645 //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 +00001646 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001647 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301648 "intfId": onuDiscInd.GetIntfId(),
1649 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001650 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001651
khenaidoo106c61a2021-08-11 18:05:46 -04001652 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301653 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001654 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301655 log.Fields{"onu": onuDev,
1656 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001657
khenaidoodc2116e2021-10-19 17:33:19 -04001658 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001659 DeviceId: onuDevice.Id,
1660 ParentDeviceId: dh.device.Id,
1661 OperStatus: common.OperStatus_DISCOVERED,
1662 ConnStatus: common.ConnectStatus_REACHABLE,
1663 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301664 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001666 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001667 }
khenaidoo106c61a2021-08-11 18:05:46 -04001668
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001670 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301671 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001672 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001673 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674 }
1675 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001676}
1677
Mahir Gunyelb0046752021-02-26 13:51:05 -08001678func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001679
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001680 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001681 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001682 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001683 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001684 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301685 log.Fields{"onuId": onuInd.OnuId,
1686 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301687 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001688 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001689 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301690
David K. Bainbridge794735f2020-02-11 21:01:37 -08001691 errFields := log.Fields{"device-id": dh.device.Id}
1692
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301693 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1694
Mahir Gunyele77977b2019-06-27 05:36:22 -07001695 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1696 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001697 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001698 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001699 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001700 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1701 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001703 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 errFields["onu-id"] = onuInd.OnuId
1705 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001706 }
khenaidoodc2116e2021-10-19 17:33:19 -04001707 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001708 ParentId: dh.device.Id,
1709 SerialNumber: serialNumber,
1710 OnuId: onuInd.OnuId,
1711 ParentPortNo: ponPort,
1712 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001713 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001714
David K. Bainbridge794735f2020-02-11 21:01:37 -08001715 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001716 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001717 }
1718
David K. Bainbridge794735f2020-02-11 21:01:37 -08001719 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001720 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001721 "previousIntfId": onuDevice.ParentPortNo,
1722 "currentIntfId": ponPort})
1723 }
1724
1725 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301727 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1728 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301729 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001730 }
1731 if !foundInCache {
1732 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1733
khenaidoo106c61a2021-08-11 18:05:46 -04001734 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 -08001735
1736 }
kesavand7cf3a052020-08-28 12:49:18 +05301737 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001738 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001739 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301740 }
1741 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001742 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001743 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001744 }
1745 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001746}
1747
Neha Sharma96b7bf22020-06-15 10:37:32 +00001748func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001749 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 -07001750 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1751 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1752 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1753 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001754 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001755 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1756 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001757 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001758 onuInd.OperState = "down"
1759 }
1760 }
1761
David K. Bainbridge794735f2020-02-11 21:01:37 -08001762 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001763 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001764 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 -04001765
khenaidoodc2116e2021-10-19 17:33:19 -04001766 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001767 DeviceId: onuDevice.Id,
1768 OnuIndication: onuInd,
1769 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001770 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301771 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001772 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001773 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001774 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001775 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001776 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001777 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001778 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001779 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001780 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001781}
1782
cuilin20187b2a8c32019-03-26 19:52:28 -07001783func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1784 if serialNum != nil {
1785 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001786 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001787 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001788}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001789func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1790 decodedStr, err := hex.DecodeString(serialNum[4:])
1791 if err != nil {
1792 return nil, err
1793 }
1794 return &oop.SerialNumber{
1795 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001796 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001797 }, nil
1798}
cuilin20187b2a8c32019-03-26 19:52:28 -07001799
1800func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001801 if len(vendorSpecific) > 3 {
1802 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1803 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1804 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1805 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1806 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1807 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1808 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1809 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1810 return tmp
1811 }
1812 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001813}
1814
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001815//UpdateFlowsBulk upates the bulk flow
1816func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301817 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001818}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001819
1820//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001821func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1822 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301823 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001824 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301825 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001826
khenaidoodc2116e2021-10-19 17:33:19 -04001827 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001828 ParentId: dh.device.Id,
1829 OnuId: onuID,
1830 ParentPortNo: parentPort,
1831 })
1832
Girish Gowdru0c588b22019-04-23 23:24:56 -04001833 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001834 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001835 "intf-id": parentPort,
1836 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001837 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838 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 -08001839 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301840}
1841
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001842// SendPacketInToCore sends packet-in to core
1843// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1844// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001845func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001846 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001847 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001848 "port": logicalPort,
1849 "packet": hex.EncodeToString(packetPayload),
1850 "device-id": dh.device.Id,
1851 })
1852 }
khenaidoo106c61a2021-08-11 18:05:46 -04001853
khenaidoodc2116e2021-10-19 17:33:19 -04001854 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001855 DeviceId: dh.device.Id,
1856 Port: logicalPort,
1857 Packet: packetPayload,
1858 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301859 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001860 "source": "adapter",
1861 "destination": "core",
1862 "device-id": dh.device.Id,
1863 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001864 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001865 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001866 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001867 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001868 "packet": hex.EncodeToString(packetPayload),
1869 "device-id": dh.device.Id,
1870 })
1871 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001872 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001873}
1874
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001875// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001876func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001877 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001878
1879 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1880 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001881 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001882 }
1883
Kent Hagermane6ff1012020-07-14 15:07:53 -04001884 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001885 metrics := dh.metrics.GetSubscriberMetrics()
1886 for _, m := range pmConfigs.Metrics {
1887 metrics[m.Name].Enabled = m.Enabled
1888
1889 }
1890 }
1891}
1892
khenaidoodc2116e2021-10-19 17:33:19 -04001893func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001894 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001895 var errorsList []error
1896
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001897 if dh.getDeviceDeletionInProgressFlag() {
1898 // The device itself is going to be reset as part of deletion. So nothing to be done.
1899 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1900 return nil
1901 }
1902
Girish Gowdru0c588b22019-04-23 23:24:56 -04001903 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001904 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001905 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001906
Neha Sharma96b7bf22020-06-15 10:37:32 +00001907 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301908 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001909 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301910 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001911 if flow_utils.HasGroup(flow) {
1912 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1913 } else {
yasin saplid0566272021-12-21 09:10:30 +00001914 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
Girish Gowdra491a9c62021-01-06 16:43:07 -08001915 }
Girish Gowdracefae192020-03-19 18:14:10 -07001916 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01001917 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
1918 //The flow we want to remove is not there, there is no need to throw an error
1919 logger.Warnw(ctx, "flow-to-remove-not-found",
1920 log.Fields{
1921 "ponIf": intfID,
1922 "flowToRemove": flow,
1923 "error": err,
1924 })
1925 } else {
1926 errorsList = append(errorsList, err)
1927 }
Girish Gowdracefae192020-03-19 18:14:10 -07001928 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001929 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301930
1931 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00001932 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001933 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301934 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001935 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301936 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001937 if flow_utils.HasGroup(flow) {
1938 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1939 } else {
yasin saplid0566272021-12-21 09:10:30 +00001940 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001941 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1942 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1943 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1944 } else {
yasin saplid0566272021-12-21 09:10:30 +00001945 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001946 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001947 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001948 if err != nil {
1949 errorsList = append(errorsList, err)
1950 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301951 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001952 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001953
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001954 return errorsList
1955}
1956
1957func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1958 var err error
1959 var errorsList []error
1960
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001961 if dh.getDeviceDeletionInProgressFlag() {
1962 // The device itself is going to be reset as part of deletion. So nothing to be done.
1963 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1964 return nil
1965 }
1966
Girish Gowdracefae192020-03-19 18:14:10 -07001967 // 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 +00001968 if groups != nil {
1969 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001970 // err = dh.groupMgr.AddGroup(ctx, group)
1971 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001972 if err != nil {
1973 errorsList = append(errorsList, err)
1974 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001975 }
1976 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001977 // err = dh.groupMgr.ModifyGroup(ctx, group)
1978 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001979 if err != nil {
1980 errorsList = append(errorsList, err)
1981 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001982 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001983 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001984 // err = dh.groupMgr.DeleteGroup(ctx, group)
1985 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001986 if err != nil {
1987 errorsList = append(errorsList, err)
1988 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001989 }
1990 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001991
1992 return errorsList
1993}
1994
1995//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001996func (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 -07001997
1998 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001999
2000 if dh.getDeviceDeletionInProgressFlag() {
2001 // The device itself is going to be reset as part of deletion. So nothing to be done.
2002 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
2003 return nil
2004 }
2005
Girish Gowdra0fb24a32021-10-27 15:15:27 -07002006 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
2007 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
2008 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002009 if len(errorsList) > 0 {
2010 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
2011 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002012 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04002013 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302014}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002015
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002016//DisableDevice disables the given device
2017//It marks the following for the given device:
2018//Device-Handler Admin-State : down
2019//Device Port-State: UNKNOWN
2020//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00002021func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04002022 /* On device disable ,admin state update has to be done prior sending request to agent since
2023 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002024 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002025 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002026 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002027 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002028 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002029 }
Chaitrashree G S44124192019-08-07 20:21:36 -04002030 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002031 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04002032 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002033 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302034
2035 dh.discOnus = sync.Map{}
2036 dh.onus = sync.Map{}
2037
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002038 dh.lockDevice.RLock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302039 //stopping the stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002040 if dh.isCollectorActive {
2041 dh.stopCollector <- true
2042 }
2043 dh.lockDevice.RUnlock()
Thomas Lee S85f37312020-04-03 17:06:12 +05302044
Neha Sharma96b7bf22020-06-15 10:37:32 +00002045 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002046 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05302047 //Update device Admin state
2048 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04002049
kdarapu1afeceb2020-02-12 01:38:09 -05002050 // 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 -04002051 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002052 DeviceId: cloned.Id,
2053 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2054 OperStatus: voltha.OperStatus_UNKNOWN,
2055 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002056 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002057 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002058 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002059 return nil
2060}
2061
Neha Sharma96b7bf22020-06-15 10:37:32 +00002062func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002063 // Update onu state as unreachable in onu adapter
2064 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302065 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002066
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002067 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002068 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002069 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002070 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 -04002071 }
2072 if onuDevices != nil {
2073 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002074 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002075 DeviceId: onuDevice.Id,
2076 OnuIndication: &onuInd,
2077 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002078 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002079 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002080 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002081 }
2082
2083 }
2084 }
2085
2086}
2087
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002088//ReenableDevice re-enables the olt device after disable
2089//It marks the following for the given device:
2090//Device-Handler Admin-State : up
2091//Device Port-State: ACTIVE
2092//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002093func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002094 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302095 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002096 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302097 }
2098 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002099 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002100
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002101 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002102 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002103 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002104 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002105 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2106 } else {
2107 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2108 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2109 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002110 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002111 if retError == nil {
2112 //Update the device oper status as ACTIVE
2113 device.OperStatus = voltha.OperStatus_ACTIVE
2114 } else {
2115 //Update the device oper status as FAILED
2116 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002117 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002118 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002119
khenaidoodc2116e2021-10-19 17:33:19 -04002120 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002121 DeviceId: device.Id,
2122 OperStatus: device.OperStatus,
2123 ConnStatus: device.ConnectStatus,
2124 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302125 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002126 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002127 "connect-status": device.ConnectStatus,
2128 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002129 }
kesavand39e0aa32020-01-28 20:58:50 -05002130
Neha Sharma96b7bf22020-06-15 10:37:32 +00002131 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002132
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002133 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002134}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002135
npujarec5762e2020-01-01 14:08:48 +05302136func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002137 var uniID uint32
2138 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302139 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002140 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002141 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002142 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002143 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002144 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002145 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002146 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002147 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002148 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002149 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002150 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00002151 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002152 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002153 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002154 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00002155 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002156 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302157 }
yasin saplibddc2d72022-02-08 13:10:17 +00002158 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2159 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002160 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302161 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002162 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002163 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002164 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 +00002165 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002166 }
2167 return nil
2168}
2169
Devmalya Paul495b94a2019-08-27 19:42:00 -04002170// 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 +05302171func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002172 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002173 /* Clear the KV store data associated with the all the UNI ports
2174 This clears up flow data and also resource map data for various
2175 other pon resources like alloc_id and gemport_id
2176 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002177
2178 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002179 var wg sync.WaitGroup
2180 wg.Add(1) // for the mcast routine below to finish
2181 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2182 for _, flMgr := range dh.flowMgr {
2183 wg.Add(1) // for the flow handler routine below to finish
2184 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2185 }
2186 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2187 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2188 } else {
2189 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2190 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002191
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002192 dh.cleanupDeviceResources(ctx)
2193 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002194
Himani Chawla49a5d562020-11-25 11:53:44 +05302195 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002196 // Stop the Stats collector
2197 if dh.isCollectorActive {
2198 dh.stopCollector <- true
2199 }
2200 // stop the heartbeat check routine
2201 if dh.isHeartbeatCheckActive {
2202 dh.stopHeartbeatCheck <- true
2203 }
Himani Chawla49a5d562020-11-25 11:53:44 +05302204 // Stop the read indication only if it the routine is active
2205 if dh.isReadIndicationRoutineActive {
2206 dh.stopIndications <- true
2207 }
2208 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002209 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002210 //Reset the state
2211 if dh.Client != nil {
2212 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302213 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002214 }
2215 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002216 // There is no need to update the core about operation status and connection status of the OLT.
2217 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2218 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2219 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002220
khenaidoo7eb2d672021-10-22 19:08:50 -04002221 // Stop the adapter grpc clients for that parent device
2222 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002223 return nil
2224}
Kent Hagermane6ff1012020-07-14 15:07:53 -04002225func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002226
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002227 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302228 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002229 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002230 var err error
yasin sapli9e4c5092022-02-01 13:52:33 +00002231 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002232 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002233 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002234 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002235 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302236 }
2237 }
yasin saplibddc2d72022-02-08 13:10:17 +00002238 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx)
2239 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002240 dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002241 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2242 logger.Debug(ctx, err)
2243 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002244 }
yasin saplibddc2d72022-02-08 13:10:17 +00002245 // Clean up NNI manager's data
2246 _ = dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002247 }
A R Karthick1f85b802019-10-11 05:06:05 +00002248
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002249 // Take one final sweep at cleaning up KV store for the OLT device
2250 // Clean everything at <base-path-prefix>/openolt/<device-id>
2251 kvClient, err := kvstore.NewEtcdClient(ctx, dh.openOLT.KVStoreAddress, rsrcMgr.KvstoreTimeout, log.FatalLevel)
2252 if err == nil {
2253 kvBackend := &db.Backend{
2254 Client: kvClient,
2255 StoreType: dh.openOLT.KVStoreType,
2256 Address: dh.openOLT.KVStoreAddress,
2257 Timeout: rsrcMgr.KvstoreTimeout,
2258 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, dh.cm.Backend.PathPrefix, dh.device.Id)}
2259 _ = kvBackend.DeleteWithPrefix(ctx, "")
2260 }
2261
Devmalya Paul495b94a2019-08-27 19:42:00 -04002262 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302263 dh.onus.Range(func(key interface{}, value interface{}) bool {
2264 dh.onus.Delete(key)
2265 return true
2266 })
2267
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002268 /*Delete discovered ONU map for the device*/
2269 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2270 dh.discOnus.Delete(key)
2271 return true
2272 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002273}
2274
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002275//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002276func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002277 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302278 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002279 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002280 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002281 return nil
2282}
2283
David K. Bainbridge794735f2020-02-11 21:01:37 -08002284func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002285 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002286 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002287 "packet-indication": *packetIn,
2288 "device-id": dh.device.Id,
2289 "packet": hex.EncodeToString(packetIn.Pkt),
2290 })
2291 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002292 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002293 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002294 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002295 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002296 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002297 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002298 "logical-port-num": logicalPortNum,
2299 "device-id": dh.device.Id,
2300 "packet": hex.EncodeToString(packetIn.Pkt),
2301 })
2302 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002303
khenaidoodc2116e2021-10-19 17:33:19 -04002304 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002305 DeviceId: dh.device.Id,
2306 Port: logicalPortNum,
2307 Packet: packetIn.Pkt,
2308 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302309 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002310 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302311 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002312 "device-id": dh.device.Id,
2313 "packet": hex.EncodeToString(packetIn.Pkt),
2314 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002315 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002316
Matteo Scandolo92186242020-06-12 10:54:18 -07002317 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002319 "packet": hex.EncodeToString(packetIn.Pkt),
2320 "device-id": dh.device.Id,
2321 })
2322 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002323 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002324}
2325
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002326// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002327func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002328 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002330 "device-id": dh.device.Id,
2331 "egress-port-no": egressPortNo,
2332 "pkt-length": len(packet.Data),
2333 "packet": hex.EncodeToString(packet.Data),
2334 })
2335 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002336
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002337 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002338 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002339 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2340 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302341 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2342 // Do not packet-out lldp packets on uni port.
2343 // ONOS has no clue about uni/nni ports, it just packets out on all
2344 // available ports on the Logical Switch. It should not be interested
2345 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002346 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002347 "device-id": dh.device.Id,
2348 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302349 return nil
2350 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002351 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2352 if innerEthType == 0x8100 {
2353 // q-in-q 802.1ad or 802.1q double tagged packet.
2354 // slice out the outer tag.
2355 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002356 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002357 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002358 "packet-data": hex.EncodeToString(packet.Data),
2359 "device-id": dh.device.Id,
2360 })
2361 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002362 }
2363 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002364 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2365 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2366 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002367
Girish Gowdra9602eb42020-09-09 15:50:39 -07002368 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002369 if err != nil {
2370 // In this case the openolt agent will receive the gemPortID as 0.
2371 // The agent tries to retrieve the gemPortID in this case.
2372 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002373 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002374 "intf-id": intfID,
2375 "onu-id": onuID,
2376 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002377 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302378 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002379 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002380 }
2381
2382 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002383 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002385 "egress-port-no": egressPortNo,
2386 "intf-id": intfID,
2387 "onu-id": onuID,
2388 "uni-id": uniID,
2389 "gem-port-id": gemPortID,
2390 "packet": hex.EncodeToString(packet.Data),
2391 "device-id": dh.device.Id,
2392 })
2393 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002394
npujarec5762e2020-01-01 14:08:48 +05302395 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302396 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002397 "source": "adapter",
2398 "destination": "onu",
2399 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002400 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002401 "oni-id": onuID,
2402 "uni-id": uniID,
2403 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002404 "packet": hex.EncodeToString(packet.Data),
2405 "device-id": dh.device.Id,
2406 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002407 }
2408 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002409 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002410 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002411 return olterrors.NewErrInvalidValue(log.Fields{
2412 "egress-nni-port": egressPortNo,
2413 "device-id": dh.device.Id,
2414 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002415 }
2416 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002417
Matteo Scandolo92186242020-06-12 10:54:18 -07002418 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002419 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002420 "uplink-pkt": uplinkPkt,
2421 "packet": hex.EncodeToString(packet.Data),
2422 "device-id": dh.device.Id,
2423 })
2424 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002425
npujarec5762e2020-01-01 14:08:48 +05302426 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002427 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2428 "packet": hex.EncodeToString(packet.Data),
2429 "device-id": dh.device.Id,
2430 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002431 }
2432 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002433 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302434 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002435 "egressPortType": egressPortType,
2436 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302437 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002438 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002439 }
2440 return nil
2441}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002442
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002443func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2444 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002445}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302446
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002447func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002448
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002449 defer func() {
2450 dh.lockDevice.Lock()
2451 dh.isHeartbeatCheckActive = false
2452 dh.lockDevice.Unlock()
2453 }()
2454
2455 dh.lockDevice.Lock()
2456 dh.isHeartbeatCheckActive = true
2457 dh.lockDevice.Unlock()
2458
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302459 // start the heartbeat check towards the OLT.
2460 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302461 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302462
2463 for {
2464 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2465 select {
2466 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002467 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002468 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002469 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302470 if timerCheck == nil {
2471 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002472 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302473 }
2474 } else {
2475 if timerCheck != nil {
2476 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002477 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302478 }
2479 timerCheck = nil
2480 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302481 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2482 if dh.heartbeatSignature == 0 {
2483 // First time the signature will be 0, update the signture to DB when not found.
2484 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2485 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2486 }
2487 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2488
2489 dh.lockDevice.RLock()
2490 // Stop the read indication only if it the routine is active
2491 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2492 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2493 // on next execution of the readIndication routine.
2494 if !dh.isReadIndicationRoutineActive {
2495 // Start reading indications
2496 go func() {
2497 if err = dh.readIndications(ctx); err != nil {
2498 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2499 }
2500 }()
2501 }
2502 dh.lockDevice.RUnlock()
2503
2504 } else {
2505 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2506 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2507 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2508 go dh.updateStateRebooted(ctx)
2509 }
2510
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302511 }
2512 cancel()
2513 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002514 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302515 return
2516 }
2517 }
2518}
2519
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002520func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002521 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002522 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002523 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2524 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2525 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2526 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2527 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002528 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002529 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2530 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002531 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302532
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302533 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002534 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002535 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002536 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002537 DeviceId: dh.device.Id,
2538 OperStatus: voltha.OperStatus_UNKNOWN,
2539 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2540 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002541 _ = 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 -04002542 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302543 /*
2544 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2545 DeviceId: dh.device.Id,
2546 PortTypeFilter: 0,
2547 OperStatus: voltha.OperStatus_UNKNOWN,
2548 }); err != nil {
2549 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2550 }
2551 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002552
2553 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002554 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002555 cloned := proto.Clone(device).(*voltha.Device)
2556 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2557 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2558 dh.device = cloned // update local copy of the device
2559 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002560
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002561 dh.lockDevice.RLock()
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002562 // Stop the Stats collector
2563 if dh.isCollectorActive {
2564 dh.stopCollector <- true
2565 }
2566 // stop the heartbeat check routine
2567 if dh.isHeartbeatCheckActive {
2568 dh.stopHeartbeatCheck <- true
2569 }
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002570 // Stop the read indication only if it the routine is active
2571 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2572 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2573 // on next execution of the readIndication routine.
2574 if dh.isReadIndicationRoutineActive {
2575 dh.stopIndications <- true
2576 }
2577 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002578 dh.transitionMap.Handle(ctx, DeviceInit)
2579
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302580 }
2581}
kesavand39e0aa32020-01-28 20:58:50 -05002582
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302583func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2584 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2585 if err != nil || device == nil {
2586 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2587 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2588 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2589 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2590 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2591 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2592 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2593 return
2594 }
2595
2596 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2597 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2598 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2599 DeviceId: dh.device.Id,
2600 OperStatus: voltha.OperStatus_REBOOTED,
2601 ConnStatus: voltha.ConnectStatus_REACHABLE,
2602 }); err != nil {
2603 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2604 }
2605
2606 dh.lockDevice.RLock()
2607 // Stop the read indication only if it the routine is active
2608 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2609 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2610 // on next execution of the readIndication routine.
2611 if dh.isReadIndicationRoutineActive {
2612 dh.stopIndications <- true
2613 }
2614 dh.lockDevice.RUnlock()
2615
2616 //raise olt communication failure event
2617 raisedTs := time.Now().Unix()
2618 cloned := proto.Clone(device).(*voltha.Device)
2619 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2620 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2621 dh.device = cloned // update local copy of the device
2622 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2623
2624 dh.cleanupDeviceResources(ctx)
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002625
2626 dh.lockDevice.RLock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302627 // Stop the Stats collector
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002628 if dh.isCollectorActive {
2629 dh.stopCollector <- true
2630 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302631 // stop the heartbeat check routine
Holger Hildebrandte6c877b2022-09-15 13:51:39 +00002632 if dh.isHeartbeatCheckActive {
2633 dh.stopHeartbeatCheck <- true
2634 }
2635 dh.lockDevice.RUnlock()
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302636
2637 var wg sync.WaitGroup
2638 wg.Add(1) // for the multicast handler routine
2639 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2640 for _, flMgr := range dh.flowMgr {
2641 wg.Add(1) // for the flow handler routine
2642 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2643 }
2644 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2645 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2646 } else {
2647 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2648 }
2649
2650 //reset adapter reconcile flag
2651 dh.adapterPreviouslyConnected = false
2652 for {
2653
2654 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2655 if err != nil || childDevices == nil {
2656 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2657 continue
2658 }
2659 if len(childDevices.Items) == 0 {
2660 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
2661 break
2662 } else {
2663 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
2664 time.Sleep(5 * time.Second)
2665 }
2666
2667 }
2668 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
2669 dh.transitionMap.Handle(ctx, DeviceInit)
2670
2671}
2672
kesavand39e0aa32020-01-28 20:58:50 -05002673// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002674func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2675 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2676 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002677}
2678
2679// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002680func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2681 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2682 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002683}
2684
kdarapu1afeceb2020-02-12 01:38:09 -05002685//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 +00002686func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2687 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002688 if port.GetType() == voltha.Port_ETHERNET_NNI {
2689 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002690 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302691 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302692 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002693 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002694 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002695 }
2696 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002697 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002698 ponIntf := &oop.Interface{IntfId: ponID}
2699 var operStatus voltha.OperStatus_Types
2700 if enablePort {
2701 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302702 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002703
2704 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302705 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002706 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002707 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002708 }
2709 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002710 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002711 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002712 } else {
2713 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302714 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002715 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302716 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002717 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002718 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002719 }
2720 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002721 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002722 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002723 }
khenaidoodc2116e2021-10-19 17:33:19 -04002724 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002725 DeviceId: dh.device.Id,
2726 PortType: voltha.Port_PON_OLT,
2727 PortNo: port.PortNo,
2728 OperStatus: operStatus,
2729 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302730 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302731 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002732 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002733 }
2734 return nil
2735}
2736
kdarapu1afeceb2020-02-12 01:38:09 -05002737//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002738func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002739 // Disable the port and update the oper_port_status to core
2740 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002741 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002742 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002743 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302744 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302745 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002746 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002747 }
2748 }
2749 }
2750 return nil
2751}
2752
2753//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002754func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2755 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2756 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002757 if port.Type == voltha.Port_ETHERNET_NNI {
2758 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002759 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002760 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002761 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002762 }
2763 }
2764 if port.Type == voltha.Port_PON_OLT {
2765 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002766 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002767 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002768 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002769 }
2770 }
2771 }
2772}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002773
2774// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002775func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002776 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07002777 if dh.getDeviceDeletionInProgressFlag() {
2778 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
2779 // will reboot, so everything will be reset on the pOLT too.
2780 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
2781 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
2782 return nil
2783 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002784 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002785 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002786
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002787 var sn *oop.SerialNumber
2788 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002789 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302790 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002791 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302792 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002793 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002794 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002795
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002796 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002797 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00002798 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002799 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2800 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2801 "device-id": dh.device.Id,
2802 "intf-id": intfID,
2803 "onuID": onuID,
2804 "err": err})
2805 } else {
2806 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00002807 // Delete flows from device before schedulers and queue
2808 // Clear flowids for gem cache.
2809 removedFlows := []uint64{}
2810 for _, gem := range onuGem.GemPorts {
2811 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
2812 for _, flowID := range flowIDs {
2813 //multiple gem port can have the same flow id
2814 //it is better to send only one flowRemove request to the agent
2815 var alreadyRemoved bool
2816 for _, removedFlowID := range removedFlows {
2817 if removedFlowID == flowID {
2818 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
2819 alreadyRemoved = true
2820 break
2821 }
2822 }
2823 if !alreadyRemoved {
2824 flow := &oop.Flow{FlowId: flowID}
2825 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
2826 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
2827 "device-id": dh.device.Id,
2828 "onu-device": onu,
2829 "err": err})
2830 }
2831 removedFlows = appendUnique64bit(removedFlows, flowID)
2832 }
2833 }
2834 }
2835 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
2836 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002837 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2838 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2839 "device-id": dh.device.Id,
2840 "onu-device": onu,
2841 "err": err})
2842 }
yasin saplibddc2d72022-02-08 13:10:17 +00002843 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002844 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2845 "intf-id": intfID,
2846 "onu-device": onu,
2847 "onu-gem": onuGem,
2848 "err": err})
2849 //Not returning error on cleanup.
2850 }
2851 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302852
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002853 }
yasin saplibddc2d72022-02-08 13:10:17 +00002854 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002855 dh.onus.Delete(onuKey)
2856 dh.discOnus.Delete(onuSn)
2857
2858 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002859 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302860 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302861 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002862 "onu-id": onuID}, err).Log()
2863 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002864
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002865 return nil
2866}
Girish Gowdracefae192020-03-19 18:14:10 -07002867
2868func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002869 for _, field := range flow_utils.GetOfbFields(flow) {
2870 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002871 return field.GetPort()
2872 }
2873 }
2874 return InvalidPort
2875}
2876
2877func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002878 for _, action := range flow_utils.GetActions(flow) {
2879 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002880 if out := action.GetOutput(); out != nil {
2881 return out.GetPort()
2882 }
2883 }
2884 }
2885 return InvalidPort
2886}
2887
Girish Gowdracefae192020-03-19 18:14:10 -07002888func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2889 inPort := getInPortFromFlow(flow)
2890 outPort := getOutPortFromFlow(flow)
2891
2892 if inPort == InvalidPort || outPort == InvalidPort {
2893 return inPort, outPort
2894 }
2895
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002896 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002897 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002898 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002899 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002900 return uniPort, outPort
2901 }
2902 }
2903 } else {
2904 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002905 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002906 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002907 return inPort, uniPort
2908 }
2909 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002910 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002911 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002912 return uniPort, outPort
2913 }
2914 }
2915 }
2916
2917 return InvalidPort, InvalidPort
2918}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002919
2920func extractOmciTransactionID(omciPkt []byte) uint16 {
2921 if len(omciPkt) > 3 {
2922 d := omciPkt[0:2]
2923 transid := binary.BigEndian.Uint16(d)
2924 return transid
2925 }
2926 return 0
2927}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002928
2929// StoreOnuDevice stores the onu parameters to the local cache.
2930func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2931 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2932 dh.onus.Store(onuKey, onuDevice)
2933}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002934
khenaidoodc2116e2021-10-19 17:33:19 -04002935func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002936 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002937 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002938 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002939 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002940 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002941 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002942 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002943 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2944 return nil, err
2945 }
2946 ID = device.ProxyAddress.GetOnuId()
2947 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2948 valueparam.Onu = &Onu
2949 valueparam.Value = value
2950
2951 // This API is unsupported until agent patch is added
2952 resp.Unsupported = uint32(value)
2953 _ = ctx
2954
2955 // Uncomment this code once agent changes are complete and tests
2956 /*
2957 resp, err = dh.Client.GetValue(ctx, valueparam)
2958 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002959 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002960 return nil, err
2961 }
2962 */
2963
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002964 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 -08002965 return resp, nil
2966}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002967
yasin saplid0566272021-12-21 09:10:30 +00002968func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
2969 // Default to NNI
2970 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07002971 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002972 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002973 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002974 }
2975 return intfID
2976}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002977
Mahir Gunyelb0046752021-02-26 13:51:05 -08002978func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2979 dh.perPonOnuIndicationChannelLock.Lock()
2980 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2981 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002982 return ch.indicationChannel
2983 }
2984 channels := onuIndicationChannels{
2985 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002986 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002987 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002988 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002989 stopChannel: make(chan struct{}),
2990 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002991 dh.perPonOnuIndicationChannel[intfID] = channels
2992 dh.perPonOnuIndicationChannelLock.Unlock()
2993 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002994 return channels.indicationChannel
2995
2996}
2997
Mahir Gunyelb0046752021-02-26 13:51:05 -08002998func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2999 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
3000 dh.perPonOnuIndicationChannelLock.Lock()
3001 defer dh.perPonOnuIndicationChannelLock.Unlock()
3002 for _, v := range dh.perPonOnuIndicationChannel {
3003 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003004 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003005 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003006}
3007
Mahir Gunyelb0046752021-02-26 13:51:05 -08003008func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
3009 ind := onuIndicationMsg{
3010 ctx: ctx,
3011 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003012 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08003013 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003014 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08003015 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003016}
3017
Mahir Gunyelb0046752021-02-26 13:51:05 -08003018func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003019 for {
3020 select {
3021 // process one indication per onu, before proceeding to the next one
3022 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08003023 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003024 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08003025 "ind": indication})
3026 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003027 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003028 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003029 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3030 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003031 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003032 }
3033 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08003034 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003035 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
3036 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08003037 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08003038 }
3039 }
3040 case <-onuChannels.stopChannel:
3041 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
3042 close(onuChannels.indicationChannel)
3043 return
3044 }
3045 }
3046}
Girish Gowdra491a9c62021-01-06 16:43:07 -08003047
3048// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
3049// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04003050func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003051 if dh.getDeviceDeletionInProgressFlag() {
3052 // The device itself is going to be reset as part of deletion. So nothing to be done.
3053 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
3054 return nil
3055 }
3056
Girish Gowdra491a9c62021-01-06 16:43:07 -08003057 // Step1 : Fill McastFlowOrGroupControlBlock
3058 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
3059 // Step3 : Wait on response channel for response
3060 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003061 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08003062 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
3063 errChan := make(chan error)
3064 var groupID uint32
3065 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
3066 ctx: ctx,
3067 flowOrGroupAction: action,
3068 flow: flow,
3069 group: group,
3070 errChan: &errChan,
3071 }
3072 if flow != nil {
3073 groupID = flow_utils.GetGroup(flow)
3074 } else if group != nil {
3075 groupID = group.Desc.GroupId
3076 } else {
3077 return errors.New("flow-and-group-both-nil")
3078 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003079 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3080 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3081 // Derive the appropriate go routine to handle the request by a simple module operation.
3082 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3083 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3084 // Wait for handler to return error value
3085 err := <-errChan
3086 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3087 return err
3088 }
3089 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3090 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003091}
3092
3093// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003094func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003095 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003096 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003097 // block on the channel to receive an incoming mcast flow/group
3098 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003099 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3100 if mcastFlowOrGroupCb.flow != nil {
3101 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3102 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3103 log.Fields{"device-id": dh.device.Id,
3104 "flowToAdd": mcastFlowOrGroupCb.flow})
3105 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
3106 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3107 // Pass the return value over the return channel
3108 *mcastFlowOrGroupCb.errChan <- err
3109 } else { // flow remove
3110 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3111 log.Fields{"device-id": dh.device.Id,
3112 "flowToRemove": mcastFlowOrGroupCb.flow})
3113 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
3114 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3115 // Pass the return value over the return channel
3116 *mcastFlowOrGroupCb.errChan <- err
3117 }
3118 } else { // mcast group
3119 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3120 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3121 log.Fields{"device-id": dh.device.Id,
3122 "groupToAdd": mcastFlowOrGroupCb.group})
3123 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3124 // Pass the return value over the return channel
3125 *mcastFlowOrGroupCb.errChan <- err
3126 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3127 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3128 log.Fields{"device-id": dh.device.Id,
3129 "groupToModify": mcastFlowOrGroupCb.group})
3130 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3131 // Pass the return value over the return channel
3132 *mcastFlowOrGroupCb.errChan <- err
3133 } else { // group remove
3134 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3135 log.Fields{"device-id": dh.device.Id,
3136 "groupToRemove": mcastFlowOrGroupCb.group})
3137 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3138 // Pass the return value over the return channel
3139 *mcastFlowOrGroupCb.errChan <- err
3140 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003141 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003142 case <-stopHandler:
3143 dh.mcastHandlerRoutineActive[routineIndex] = false
3144 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003145 }
3146 }
3147}
kesavand62126212021-01-12 04:56:06 -05003148
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003149// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003150func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003151 for i, v := range dh.stopMcastHandlerRoutine {
3152 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003153 select {
3154 case v <- true:
3155 case <-time.After(time.Second * 5):
3156 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3157 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003158 }
3159 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003160 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003161 logger.Debug(ctx, "stopped all mcast handler routines")
3162}
3163
kesavand62126212021-01-12 04:56:06 -05003164func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3165
3166 singleValResp := extension.SingleGetValueResponse{
3167 Response: &extension.GetValueResponse{
3168 Response: &extension.GetValueResponse_PortCoutners{
3169 PortCoutners: &extension.GetOltPortCountersResponse{},
3170 },
3171 },
3172 }
3173
3174 errResp := func(status extension.GetValueResponse_Status,
3175 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3176 return &extension.SingleGetValueResponse{
3177 Response: &extension.GetValueResponse{
3178 Status: status,
3179 ErrReason: reason,
3180 },
3181 }
3182 }
3183
3184 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3185 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3186 //send error response
3187 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3188 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3189 }
3190 statIndChn := make(chan bool, 1)
3191 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3192 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3193 //request openOlt agent to send the the port statistics indication
3194
3195 go func() {
3196 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3197 if err != nil {
3198 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3199 }
3200 }()
3201 select {
3202 case <-statIndChn:
3203 //indication received for ports stats
3204 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3205 case <-time.After(oltPortInfoTimeout * time.Second):
3206 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3207 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3208 case <-ctx.Done():
3209 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3210 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3211 }
3212 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3213 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003214 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003215 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3216 cmnni := dh.portStats.collectNNIMetrics(intfID)
3217 if cmnni == nil {
3218 //TODO define the error reason
3219 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3220 }
3221 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3222 return &singleValResp
3223
3224 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3225 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003226 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003227 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3228 cmpon := dh.portStats.collectPONMetrics(intfID)
3229 if cmpon == nil {
3230 //TODO define the error reason
3231 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3232 }
3233 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3234 return &singleValResp
3235 }
3236 }
3237 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3238}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303239
3240func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3241
3242 singleValResp := extension.SingleGetValueResponse{
3243 Response: &extension.GetValueResponse{
3244 Response: &extension.GetValueResponse_OnuPonCounters{
3245 OnuPonCounters: &extension.GetOnuCountersResponse{},
3246 },
3247 },
3248 }
3249
3250 errResp := func(status extension.GetValueResponse_Status,
3251 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3252 return &extension.SingleGetValueResponse{
3253 Response: &extension.GetValueResponse{
3254 Status: status,
3255 ErrReason: reason,
3256 },
3257 }
3258 }
3259 intfID := onuPonInfo.IntfId
3260 onuID := onuPonInfo.OnuId
3261 onuKey := dh.formOnuKey(intfID, onuID)
3262
3263 if _, ok := dh.onus.Load(onuKey); !ok {
3264 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3265 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3266 }
3267 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3268 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3269 if cmnni == nil {
3270 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3271 }
3272 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3273 return &singleValResp
3274
3275}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003276
3277func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3278
3279 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3280 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3281 if err != nil {
3282 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3283 return generateSingleGetValueErrorResponse(err)
3284 }
3285 return &extension.SingleGetValueResponse{
3286 Response: &extension.GetValueResponse{
3287 Status: extension.GetValueResponse_OK,
3288 Response: &extension.GetValueResponse_RxPower{
3289 RxPower: &extension.GetRxPowerResponse{
3290 IntfId: rxPowerRequest.IntfId,
3291 OnuId: rxPowerRequest.OnuId,
3292 Status: rxPower.Status,
3293 FailReason: rxPower.FailReason.String(),
3294 RxPower: rxPower.RxPowerMeanDbm,
3295 },
3296 },
3297 },
3298 }
3299}
3300
3301func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3302 errResp := func(status extension.GetValueResponse_Status,
3303 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3304 return &extension.SingleGetValueResponse{
3305 Response: &extension.GetValueResponse{
3306 Status: status,
3307 ErrReason: reason,
3308 },
3309 }
3310 }
3311
3312 if err != nil {
3313 if e, ok := status.FromError(err); ok {
3314 switch e.Code() {
3315 case codes.Internal:
3316 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3317 case codes.DeadlineExceeded:
3318 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3319 case codes.Unimplemented:
3320 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3321 case codes.NotFound:
3322 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3323 }
3324 }
3325 }
3326
3327 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3328}
khenaidoo106c61a2021-08-11 18:05:46 -04003329
3330/*
3331Helper functions to communicate with Core
3332*/
3333
3334func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3335 cClient, err := dh.coreClient.GetCoreServiceClient()
3336 if err != nil || cClient == nil {
3337 return nil, err
3338 }
3339 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3340 defer cancel()
3341 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3342}
3343
khenaidoodc2116e2021-10-19 17:33:19 -04003344func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003345 cClient, err := dh.coreClient.GetCoreServiceClient()
3346 if err != nil || cClient == nil {
3347 return nil, err
3348 }
3349 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3350 defer cancel()
3351 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3352}
3353
khenaidoodc2116e2021-10-19 17:33:19 -04003354func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003355 cClient, err := dh.coreClient.GetCoreServiceClient()
3356 if err != nil || cClient == nil {
3357 return err
3358 }
3359 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3360 defer cancel()
3361 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3362 return err
3363}
3364
3365func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3366 cClient, err := dh.coreClient.GetCoreServiceClient()
3367 if err != nil || cClient == nil {
3368 return nil, err
3369 }
3370 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3371 defer cancel()
3372 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3373}
3374
3375func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3376 cClient, err := dh.coreClient.GetCoreServiceClient()
3377 if err != nil || cClient == nil {
3378 return nil, err
3379 }
3380 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3381 defer cancel()
3382 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3383}
3384
3385func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3386 cClient, err := dh.coreClient.GetCoreServiceClient()
3387 if err != nil || cClient == nil {
3388 return err
3389 }
3390 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3391 defer cancel()
3392 _, err = cClient.DeviceUpdate(subCtx, device)
3393 return err
3394}
3395
khenaidoodc2116e2021-10-19 17:33:19 -04003396func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003397 cClient, err := dh.coreClient.GetCoreServiceClient()
3398 if err != nil || cClient == nil {
3399 return nil, err
3400 }
3401 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3402 defer cancel()
3403 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3404}
3405
khenaidoodc2116e2021-10-19 17:33:19 -04003406func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003407 cClient, err := dh.coreClient.GetCoreServiceClient()
3408 if err != nil || cClient == nil {
3409 return err
3410 }
3411 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3412 defer cancel()
3413 _, err = cClient.SendPacketIn(subCtx, pkt)
3414 return err
3415}
3416
3417func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3418 cClient, err := dh.coreClient.GetCoreServiceClient()
3419 if err != nil || cClient == nil {
3420 return err
3421 }
3422 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3423 defer cancel()
3424 _, err = cClient.PortCreated(subCtx, port)
3425 return err
3426}
3427
khenaidoodc2116e2021-10-19 17:33:19 -04003428func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003429 cClient, err := dh.coreClient.GetCoreServiceClient()
3430 if err != nil || cClient == nil {
3431 return err
3432 }
3433 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3434 defer cancel()
3435 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3436 return err
3437}
3438
khenaidoodc2116e2021-10-19 17:33:19 -04003439func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003440 cClient, err := dh.coreClient.GetCoreServiceClient()
3441 if err != nil || cClient == nil {
3442 return err
3443 }
3444 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3445 defer cancel()
3446 _, err = cClient.PortStateUpdate(subCtx, portState)
3447 return err
3448}
3449
khenaidoodc2116e2021-10-19 17:33:19 -04003450func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003451 cClient, err := dh.coreClient.GetCoreServiceClient()
3452 if err != nil || cClient == nil {
3453 return nil, err
3454 }
3455 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3456 defer cancel()
3457 return cClient.GetDevicePort(subCtx, portFilter)
3458}
3459
3460/*
3461Helper functions to communicate with child adapter
3462*/
3463
khenaidoodc2116e2021-10-19 17:33:19 -04003464func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003465 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3466 if err != nil || aClient == nil {
3467 return err
3468 }
3469 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3470 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3471 defer cancel()
3472 _, err = aClient.OmciIndication(subCtx, response)
3473 return err
3474}
3475
khenaidoodc2116e2021-10-19 17:33:19 -04003476func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003477 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3478 if err != nil || aClient == nil {
3479 return err
3480 }
3481 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3482 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3483 defer cancel()
3484 _, err = aClient.OnuIndication(subCtx, onuInd)
3485 return err
3486}
3487
khenaidoodc2116e2021-10-19 17:33:19 -04003488func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003489 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3490 if err != nil || aClient == nil {
3491 return err
3492 }
3493 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3494 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3495 defer cancel()
3496 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3497 return err
3498}
3499
khenaidoodc2116e2021-10-19 17:33:19 -04003500func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003501 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3502 if err != nil || aClient == nil {
3503 return err
3504 }
3505 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3506 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3507 defer cancel()
3508 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3509 return err
3510}
3511
khenaidoodc2116e2021-10-19 17:33:19 -04003512func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003513 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3514 if err != nil || aClient == nil {
3515 return err
3516 }
3517 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3518 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3519 defer cancel()
3520 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3521 return err
3522}
3523
3524/*
3525Helper functions for remote communication
3526*/
3527
3528// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3529// supports is deleted
3530func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3531 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3532
3533 dh.lockChildAdapterClients.Lock()
3534 defer dh.lockChildAdapterClients.Unlock()
3535 if _, ok := dh.childAdapterClients[endpoint]; ok {
3536 // Already set
3537 return nil
3538 }
3539
3540 // Setup child's adapter grpc connection
3541 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003542 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3543 dh.cfg.AdapterEndpoint,
3544 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05003545 "onu_inter_adapter_service.OnuInterAdapterService",
3546 dh.onuInterAdapterRestarted,
3547 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003548 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3549 return err
3550 }
khenaidooefff76e2021-12-15 16:51:30 -05003551 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003552
3553 // Wait until we have a connection to the child adapter.
3554 // Unlimited retries or until context expires
3555 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3556 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3557 for {
3558 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3559 if err == nil && client != nil {
3560 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3561 break
3562 }
3563 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3564 // Backoff
3565 if err = backoff.Backoff(subCtx); err != nil {
3566 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3567 break
3568 }
3569 }
3570 return nil
3571}
3572
khenaidoodc2116e2021-10-19 17:33:19 -04003573func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003574
3575 // First check from cache
3576 dh.lockChildAdapterClients.RLock()
3577 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3578 dh.lockChildAdapterClients.RUnlock()
3579 return cgClient.GetOnuInterAdapterServiceClient()
3580 }
3581 dh.lockChildAdapterClients.RUnlock()
3582
3583 // Set the child connection - can occur on restarts
3584 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3585 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3586 cancel()
3587 if err != nil {
3588 return nil, err
3589 }
3590
3591 // Get the child client now
3592 dh.lockChildAdapterClients.RLock()
3593 defer dh.lockChildAdapterClients.RUnlock()
3594 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3595 return cgClient.GetOnuInterAdapterServiceClient()
3596 }
3597 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3598}
3599
3600func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3601 dh.lockChildAdapterClients.Lock()
3602 defer dh.lockChildAdapterClients.Unlock()
3603 for key, client := range dh.childAdapterClients {
3604 client.Stop(ctx)
3605 delete(dh.childAdapterClients, key)
3606 }
3607}
3608
khenaidooefff76e2021-12-15 16:51:30 -05003609// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
3610func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
3611 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003612 return nil
3613}
3614
khenaidooefff76e2021-12-15 16:51:30 -05003615// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
3616func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
3617 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003618 return nil
3619 }
khenaidooefff76e2021-12-15 16:51:30 -05003620 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04003621}
Girish Gowdra950326e2021-11-05 12:43:24 -07003622
3623func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3624 dh.lockDevice.Lock()
3625 defer dh.lockDevice.Unlock()
3626 dh.isDeviceDeletionInProgress = flag
3627}
3628
3629func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3630 dh.lockDevice.RLock()
3631 defer dh.lockDevice.RUnlock()
3632 return dh.isDeviceDeletionInProgress
3633}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003634
3635// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3636// Returns false if waiting timed out.
3637func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3638 c := make(chan struct{})
3639 go func() {
3640 defer close(c)
3641 wg.Wait()
3642 }()
3643 select {
3644 case <-c:
3645 return true // completed normally
3646 case <-time.After(timeout):
3647 return false // timed out
3648 }
3649}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303650
3651func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
3652 val, err := json.Marshal(signature)
3653 if err != nil {
3654 logger.Error(ctx, "failed-to-marshal")
3655 return
3656 }
3657 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
3658 logger.Error(ctx, "failed-to-store-hearbeat-signature")
3659 }
3660}
3661
3662func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
3663 var signature uint32
3664
3665 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
3666 if er == nil {
3667 if Value != nil {
3668 Val, er := kvstore.ToByte(Value.Value)
3669 if er != nil {
3670 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
3671 return signature
3672 }
3673 if er = json.Unmarshal(Val, &signature); er != nil {
3674 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
3675 return signature
3676 }
3677 }
3678 }
3679 return signature
3680}