blob: 500dbf194e82be40992822d5a0ee9a988aaaced6 [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
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700102 discOnus sync.Map
103 onus sync.Map
104 portStats *OpenOltStatisticsMgr
105 metrics *pmmetrics.PmMetrics
106 stopCollector chan bool
107 stopHeartbeatCheck chan bool
108 activePorts sync.Map
109 stopIndications chan bool
110 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700111
Mahir Gunyelb0046752021-02-26 13:51:05 -0800112 totalPonPorts uint32
113 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
114 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800115
116 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
117 // 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 -0700118 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
119 stopMcastHandlerRoutine []chan bool
120 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000121
122 adapterPreviouslyConnected bool
123 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700124
125 isDeviceDeletionInProgress bool
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530126 heartbeatSignature uint32
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700127}
128
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700129//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700130type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400131 deviceID string
132 deviceType string
133 serialNumber string
134 onuID uint32
135 intfID uint32
136 proxyDeviceID string
137 losRaised bool
138 rdiRaised bool
139 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700140}
141
Mahir Gunyelb0046752021-02-26 13:51:05 -0800142type onuIndicationMsg struct {
143 ctx context.Context
144 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800145}
146
147type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800148 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800149 stopChannel chan struct{}
150}
151
Girish Gowdra491a9c62021-01-06 16:43:07 -0800152//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
153//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
154//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
155//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
156type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400157 ctx context.Context // Flow/group handler context
158 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
159 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
160 group *of.OfpGroupEntry // Group message (can be nil or valid group)
161 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800162}
163
Naga Manjunath7615e552019-10-11 22:35:47 +0530164var pmNames = []string{
165 "rx_bytes",
166 "rx_packets",
167 "rx_mcast_packets",
168 "rx_bcast_packets",
169 "tx_bytes",
170 "tx_packets",
171 "tx_mcast_packets",
172 "tx_bcast_packets",
173}
174
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700175//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400176func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700177 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700178 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700179 device.deviceType = deviceTp
180 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700181 device.onuID = onuID
182 device.intfID = intfID
183 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530184 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400185 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700186 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530187}
188
189//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400190func 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 -0700191 var dh DeviceHandler
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530192 ctx := context.Background()
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800193 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400194 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400195 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700196 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700197 dh.device = cloned
198 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500199 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700200 dh.lockDevice = sync.RWMutex{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800201 dh.stopCollector = make(chan bool, 2) // TODO: Why buffered?
202 dh.stopHeartbeatCheck = make(chan bool, 2) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530203 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 -0500204 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800205 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800206 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400207 dh.childAdapterClients = make(map[string]*vgrpc.Client)
208 dh.cfg = cfg
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530209 kvStoreDevicePath := fmt.Sprintf(dh.cm.Backend.PathPrefix, "/%s/", dh.device.Id)
210 dh.kvStore = SetKVClient(ctx, dh.openOLT.KVStoreType, dh.openOLT.KVStoreAddress, dh.device.Id, kvStoreDevicePath)
211 if dh.kvStore == nil {
212 logger.Error(ctx, "Failed to setup KV store")
213 return nil
214 }
215
Girish Gowdra491a9c62021-01-06 16:43:07 -0800216 // Create a slice of buffered channels for handling concurrent mcast flow/group.
217 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700218 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
219 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800220 for i := range dh.incomingMcastFlowOrGroup {
221 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800222 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800223 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
224 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
225 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
226 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700227 dh.mcastHandlerRoutineActive[i] = true
228 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800229 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700230 //TODO initialize the support classes.
231 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530232}
233
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530234func newKVClient(ctx context.Context, storeType string, address string, timeout time.Duration) (kvstore.Client, error) {
235 logger.Infow(ctx, "kv-store-type", log.Fields{"store": storeType})
236 switch storeType {
237 case "etcd":
238 return kvstore.NewEtcdClient(ctx, address, timeout, log.FatalLevel)
239 }
240 return nil, errors.New("unsupported-kv-store")
241}
242
243// SetKVClient sets the KV client and return a kv backend
244func SetKVClient(ctx context.Context, backend string, addr string, DeviceID string, basePathKvStore string) *db.Backend {
245 kvClient, err := newKVClient(ctx, backend, addr, rsrcMgr.KvstoreTimeout)
246 if err != nil {
247 logger.Fatalw(ctx, "Failed to init KV client\n", log.Fields{"err": err})
248 return nil
249 }
250
251 kvbackend := &db.Backend{
252 Client: kvClient,
253 StoreType: backend,
254 Address: addr,
255 Timeout: rsrcMgr.KvstoreTimeout,
256 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, basePathKvStore, DeviceID)}
257
258 return kvbackend
259}
260
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530261// start save the device to the data model
262func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700263 dh.lockDevice.Lock()
264 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000265 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700266 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000267 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530268}
269
khenaidooefff76e2021-12-15 16:51:30 -0500270// Stop stops the device handler
271func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700272 dh.lockDevice.Lock()
273 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000274 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500275 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400276
khenaidooefff76e2021-12-15 16:51:30 -0500277 // Delete (which will stop also) all grpc connections to the child adapters
278 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000279 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530280}
281
ssiddiqui04386ee2021-08-23 21:58:25 +0530282func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
283 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
284 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
285 if pooledIntfID == intfID {
286 return resourceRanges.GetTechnology()
287 }
288 }
289 }
290 return ""
291}
292
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400293func macifyIP(ip net.IP) string {
294 if len(ip) > 0 {
295 oct1 := strconv.FormatInt(int64(ip[12]), 16)
296 oct2 := strconv.FormatInt(int64(ip[13]), 16)
297 oct3 := strconv.FormatInt(int64(ip[14]), 16)
298 oct4 := strconv.FormatInt(int64(ip[15]), 16)
299 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
300 }
301 return ""
302}
303
Neha Sharma96b7bf22020-06-15 10:37:32 +0000304func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400305 var genmac string
306 var addr net.IP
307 var ips []string
308 var err error
309
Neha Sharma96b7bf22020-06-15 10:37:32 +0000310 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400311
312 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000313 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400314
315 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000316 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400317 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000318 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400319 }
320 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530322 log.Fields{"host": ips[0],
323 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400324 return genmac, nil
325 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000326 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400327 }
328
329 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000330 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530331 log.Fields{"host": host,
332 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400333 return genmac, nil
334}
335
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530336func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700337 slist := strings.Split(mac, ":")
338 result := make([]uint32, len(slist))
339 var err error
340 var tmp int64
341 for index, val := range slist {
342 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
343 return []uint32{1, 2, 3, 4, 5, 6}
344 }
345 result[index] = uint32(tmp)
346 }
347 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530348}
349
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700350//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 -0800351func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530352
David K. Bainbridge794735f2020-02-11 21:01:37 -0800353 switch portType {
354 case voltha.Port_ETHERNET_NNI:
355 return fmt.Sprintf("nni-%d", portNum), nil
356 case voltha.Port_PON_OLT:
357 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700358 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800359
Girish Kumarf26e4882020-03-05 06:49:10 +0000360 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530361}
362
Elia Battiston596406d2022-02-02 12:19:00 +0100363func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
364 if speedMbps == 0 {
365 //In case it was not set in the indication
366 //and no other value was provided
367 speedMbps = defaultPortSpeedMbps
368 }
369
370 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
371 switch speedMbps {
372 case 1000000:
373 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
374 case 100000:
375 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
376 case 40000:
377 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
378 case 10000:
379 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
380 case 1000:
381 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
382 case 100:
383 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
384 case 10:
385 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
386 }
387
388 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
389
390 port := &of.OfpPort{
391 HwAddr: macAddressToUint32Array(macAddress),
392 Config: 0,
393 State: uint32(of.OfpPortState_OFPPS_LIVE),
394 Curr: capacity,
395 Advertised: capacity,
396 Peer: capacity,
397 CurrSpeed: speedMbps * 1000, //kbps
398 MaxSpeed: speedMbps * 1000, //kbps
399 }
400
401 return port
402}
403
404func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000405 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700406 if state == "up" {
407 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500408 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500409 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700410 } else {
411 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500412 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700413 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700414 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400415 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800416 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000417 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400418 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500419
khenaidoo106c61a2021-08-11 18:05:46 -0400420 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400421 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400422 DeviceId: dh.device.Id,
423 Port: portNum,
424 })
425 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000426 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400427 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400428 DeviceId: dh.device.Id,
429 PortType: portType,
430 PortNo: portNum,
431 OperStatus: operStatus})
432 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400433 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
434 "device-id": dh.device.Id,
435 "port-type": portType,
436 "port-number": portNum,
437 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500438 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400439 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500440 }
khenaidoo106c61a2021-08-11 18:05:46 -0400441
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400442 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400443 port = &voltha.Port{
444 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700445 PortNo: portNum,
446 Label: label,
447 Type: portType,
448 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100449 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700450 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000451 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700452 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400453 err = dh.createPortInCore(ctx, port)
454 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000455 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800456 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000457 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400458 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000459 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530460 return nil
461}
462
Kent Hagermane6ff1012020-07-14 15:07:53 -0400463func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400464 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530465 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400466 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
467 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530468 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800469 dh.lockDevice.Lock()
470 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530471 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530472}
473
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700474// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530475// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800476func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000477 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700478 defer func() {
479 dh.lockDevice.Lock()
480 dh.isReadIndicationRoutineActive = false
481 dh.lockDevice.Unlock()
482 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700483 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700484 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700485 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700486 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400487
David Bainbridgef5879ca2019-12-13 21:17:54 +0000488 // Create an exponential backoff around re-enabling indications. The
489 // maximum elapsed time for the back off is set to 0 so that we will
490 // continue to retry. The max interval defaults to 1m, but is set
491 // here for code clarity
492 indicationBackoff := backoff.NewExponentialBackOff()
493 indicationBackoff.MaxElapsedTime = 0
494 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700495
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700496 dh.lockDevice.Lock()
497 dh.isReadIndicationRoutineActive = true
498 dh.lockDevice.Unlock()
499
Girish Gowdra3f974912020-03-23 20:35:18 -0700500Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700501 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400502 select {
503 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000504 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700505 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400506 default:
507 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100508
509 select {
510 case <-indications.Context().Done():
511 if err != nil {
512 logger.Warnw(ctx, "error-during-enable-indications",
513 log.Fields{"err": err,
514 "device-id": dh.device.Id})
515 }
516
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400517 // Use an exponential back off to prevent getting into a tight loop
518 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100519 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
520 "device-id": dh.device.Id,
521 "duration": duration,
522 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400523 if duration == backoff.Stop {
524 // If we reach a maximum then warn and reset the backoff
525 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100526 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530527 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530528 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400529 indicationBackoff.Reset()
530 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700531
532 // On failure process a backoff timer while watching for stopIndications
533 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700534 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700535 select {
536 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000537 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700538 if !backoffTimer.Stop() {
539 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700540 }
541 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700542 case <-backoffTimer.C:
543 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700544 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700545 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
546 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400547 }
548 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100549 default:
550 if err != nil {
551 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530552 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530553 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100554 // Close the stream, and re-initialize it
555 if err = indications.CloseSend(); err != nil {
556 // Ok to ignore here, because we landed here due to a problem on the stream
557 // In all probability, the closeSend call may fail
558 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
559 log.Fields{"err": err,
560 "device-id": dh.device.Id})
561 }
562 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
563 return err
564 }
565 // once we re-initialized the indication stream, continue to read indications
566 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700567 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100568 // Reset backoff if we have a successful receive
569 indicationBackoff.Reset()
570 // When OLT is admin down, ignore all indications.
571 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
572 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
573 log.Fields{"indication": indication,
574 "device-id": dh.device.Id})
575 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700576 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100577 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530578 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700579 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700580 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700581 // Close the send stream
582 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700583
Girish Gowdra3f974912020-03-23 20:35:18 -0700584 return nil
585}
586
587func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700588 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700589 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
590 if err != nil {
591 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
592 }
593 if indications == nil {
594 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
595 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700596 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700597 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400598}
599
600// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
601func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
602 switch indication.Data.(type) {
603 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
604 return true
605
606 default:
607 return false
608 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609}
610
David K. Bainbridge794735f2020-02-11 21:01:37 -0800611func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700612 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000613 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530614 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700615 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530616 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000618 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000619 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530620 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000621 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800622 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000623 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800624 }
625 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700626}
627
David K. Bainbridge794735f2020-02-11 21:01:37 -0800628// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530629func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700630 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700631 switch indication.Data.(type) {
632 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000633 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
634 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700635 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 -0800636 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400637 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800638 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700639 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000640 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
641 defer span.Finish()
642
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700643 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800644 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100645 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400646 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800647 }
648 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000649 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700650 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000651 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
652 defer span.Finish()
653
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700654 intfOperInd := indication.GetIntfOperInd()
655 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800656 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100657 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400658 _ = 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 -0800659 }
660 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700661 } else if intfOperInd.GetType() == "pon" {
662 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
663 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800664 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100665 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400666 _ = 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 -0800667 }
668 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000669 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000671 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530672 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530673 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700674 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000675 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
676 defer span.Finish()
677
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700678 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000679 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800680 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800681 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700682 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000683 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
684 defer span.Finish()
685
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700686 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000687 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800688 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800689 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700690 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000691 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
692 defer span.Finish()
693
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700694 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000695 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 -0800696 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000697 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400698 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800699 }
700 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000702 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
703 defer span.Finish()
704
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700705 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000706 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700707 "intf-type": pktInd.IntfId,
708 "intf-id": pktInd.IntfId,
709 "gem-port-id": pktInd.GemportId,
710 "port-no": pktInd.PortNo,
711 "device-id": dh.device.Id,
712 })
713
714 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000715 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700716 "intf-type": pktInd.IntfId,
717 "intf-id": pktInd.IntfId,
718 "gem-port-id": pktInd.GemportId,
719 "port-no": pktInd.PortNo,
720 "packet": hex.EncodeToString(pktInd.Pkt),
721 "device-id": dh.device.Id,
722 })
723 }
724
David K. Bainbridge794735f2020-02-11 21:01:37 -0800725 go func() {
726 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400727 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800728 }
729 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700730 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000731 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
732 defer span.Finish()
733
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700734 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700735 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700736 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000737 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
738 defer span.Finish()
739
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700740 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000741 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700742 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000743 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
744 defer span.Finish()
745
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700746 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000747 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
748 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700749 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530750}
751
752// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530753func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530754 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000755 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530756
Girish Gowdra618fa572021-09-01 17:19:29 -0700757 // instantiate the mcast handler routines.
758 for i := range dh.incomingMcastFlowOrGroup {
759 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
760 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
761 if !dh.mcastHandlerRoutineActive[i] {
762 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
763 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
764 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
765 // for incoming mcast flow/group to be processed serially.
766 dh.mcastHandlerRoutineActive[i] = true
767 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
768 }
769 }
770
Girish Gowdru0c588b22019-04-23 23:24:56 -0400771 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400772 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400773 DeviceId: dh.device.Id,
774 OperStatus: voltha.OperStatus_ACTIVE,
775 ConnStatus: voltha.ConnectStatus_REACHABLE,
776 }); err != nil {
777 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400778 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000779
780 //Clear olt communication failure event
781 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
782 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700783 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000784 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
785
Girish Gowdru0c588b22019-04-23 23:24:56 -0400786 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530787}
788
789// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530790func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000791 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400792
khenaidoo106c61a2021-08-11 18:05:46 -0400793 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400794 if err != nil || device == nil {
795 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000796 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400797 }
798
799 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400800
801 //Update the device oper state and connection status
802 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800803 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400804 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800805 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400806
khenaidoodc2116e2021-10-19 17:33:19 -0400807 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400808 DeviceId: cloned.Id,
809 OperStatus: cloned.OperStatus,
810 ConnStatus: cloned.ConnectStatus,
811 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000812 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400813 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400814
815 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400816 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400817 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000818 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400819 }
820 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400821 // Update onu state as down in onu adapter
822 onuInd := oop.OnuIndication{}
823 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400824
825 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
826 if err != nil {
827 return err
828 }
829 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400830 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400831 DeviceId: onuDevice.Id,
832 OnuIndication: &onuInd,
833 })
834 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800835 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400836 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400837 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800838 "onu-indicator": onuInd,
839 "device-type": onuDevice.Type,
840 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700841 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800842 } else {
843 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 -0700844 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400845 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800846 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700847 /* Discovered ONUs entries need to be cleared , since after OLT
848 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530849 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800850 dh.lockDevice.Unlock()
851
Neha Sharma96b7bf22020-06-15 10:37:32 +0000852 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700853 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530854}
855
856// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530857func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400858 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000859
860 // if the connection is already available, close the previous connection (olt reboot case)
861 if dh.clientCon != nil {
862 if err = dh.clientCon.Close(); err != nil {
863 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
864 } else {
865 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
866 }
867 }
868
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +0530869 logger.Debugw(ctx, "Dailing grpc", log.Fields{"device-id": dh.device.Id})
Gamze Abaka49c40b32021-05-06 09:30:41 +0000870 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000871 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
872 grpc.WithInsecure(),
873 grpc.WithBlock(),
874 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000875 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000876 )),
877 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000878 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000879 )))
880
881 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530882 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530883 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000884 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400885 }
886 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530887}
888
889// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530890func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400891 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530892 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400893 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530894}
895
896// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530897func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530898 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000899 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400900
901 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400902 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530903 if err != nil || device == nil {
904 /*TODO: needs to handle error scenarios */
905 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
906 }
907 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000908 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400909
910 cloned := proto.Clone(device).(*voltha.Device)
911 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
912 cloned.OperStatus = voltha.OperStatus_UNKNOWN
913 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400914
khenaidoodc2116e2021-10-19 17:33:19 -0400915 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400916 DeviceId: cloned.Id,
917 OperStatus: cloned.OperStatus,
918 ConnStatus: cloned.ConnectStatus,
919 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530920 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 -0400921 }
922
Chaitrashree G S44124192019-08-07 20:21:36 -0400923 // 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 +0530924 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400925 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530926 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400927 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400928 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
929 // all the modules initialized and ready to handle incoming ONUs.
930
Thomas Lee S985938d2020-05-04 11:40:41 +0530931 err = dh.initializeDeviceHandlerModules(ctx)
932 if err != nil {
933 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 -0400934 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400935
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700936 go startHeartbeatCheck(ctx, dh)
937
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400938 return nil
939 }
940
khenaidoo106c61a2021-08-11 18:05:46 -0400941 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400942 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400943 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400944 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400945 }
khenaidoo106c61a2021-08-11 18:05:46 -0400946 dh.populateActivePorts(ctx, ports.Items)
947 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400948 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400949 }
950
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400951 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530952 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 -0400953 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530954
Neha Sharma96b7bf22020-06-15 10:37:32 +0000955 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000956
957 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000958 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000959 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700960
961 go startHeartbeatCheck(ctx, dh)
962
cuilin20187b2a8c32019-03-26 19:52:28 -0700963 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530964}
965
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400966func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700967 var err error
968 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400969
970 if err != nil {
971 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
972 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700973 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
974 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +0000975 // +1 is for NNI
976 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
977 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700978 var i uint32
yasin saplid0566272021-12-21 09:10:30 +0000979 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
980 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
981 // There is only one NNI manager since multiple NNI is not supported for now
982 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700983 // Instantiate resource manager
984 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 -0700985 return olterrors.ErrResourceManagerInstantiating
986 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400987 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700988 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
989 // the KV store to manage mcast group data. Provide the first instance (0th index)
990 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
991 return olterrors.ErrGroupManagerInstantiating
992 }
yasin saplid0566272021-12-21 09:10:30 +0000993 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700994 // Instantiate flow manager
995 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
996 return olterrors.ErrFlowManagerInstantiating
997 }
Girish Gowdra76a1b092021-07-28 10:07:04 -0700998 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700999 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001000 /* TODO: Instantiate Alarm , stats , BW managers */
1001 /* Instantiating Event Manager to handle Alarms and KPIs */
1002 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
1003
1004 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001005 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001006
1007 return nil
1008
1009}
1010
Neha Sharma96b7bf22020-06-15 10:37:32 +00001011func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001012 var err error
1013 var deviceInfo *oop.DeviceInfo
1014
Neha Sharma8f4e4322020-08-06 10:51:53 +00001015 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001016
1017 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001018 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001019 }
1020 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001021 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001022 }
1023
Neha Sharma96b7bf22020-06-15 10:37:32 +00001024 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001025 dh.device.Root = true
1026 dh.device.Vendor = deviceInfo.Vendor
1027 dh.device.Model = deviceInfo.Model
1028 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1029 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1030 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1031
1032 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001033 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001034 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001036 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001037 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001038 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001039 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001040 dh.device.MacAddress = genmac
1041 } else {
1042 dh.device.MacAddress = deviceInfo.DeviceId
1043 }
1044
1045 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001046 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001047 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001048 }
1049
1050 return deviceInfo, nil
1051}
1052
Neha Sharma96b7bf22020-06-15 10:37:32 +00001053func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001054 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301055 for {
1056 select {
1057 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001058 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301059 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001060 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001061
khenaidoo106c61a2021-08-11 18:05:46 -04001062 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001063 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001064 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001065 continue
1066 }
khenaidoo106c61a2021-08-11 18:05:46 -04001067 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301068 // NNI Stats
1069 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001070 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301071 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001072 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001073 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001074 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301075 }
1076 // PON Stats
1077 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001078 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301079 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1080 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001081 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001082 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301083 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001085
yasin sapli9e4c5092022-02-01 13:52:33 +00001086 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001087 if len(onuGemInfoLst) > 0 {
1088 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001089 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001090 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301091 }
1092 }
1093 }
1094}
1095
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001096//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301097func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001098 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001099 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301100 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301101
1102 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001103 cgClient, err := dh.coreClient.GetCoreServiceClient()
1104 if err != nil {
1105 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1106 return
1107 }
1108
1109 // Now, set the initial PM configuration for that device
1110 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001111 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301112 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301113}
1114
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001115//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001116func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1117 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001118 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301119 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001120 HwDesc: "open_pon",
1121 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001122 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001123 },
1124 SwitchFeatures: &of.OfpSwitchFeatures{
1125 NBuffers: 256,
1126 NTables: 2,
1127 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1128 of.OfpCapabilities_OFPC_TABLE_STATS |
1129 of.OfpCapabilities_OFPC_PORT_STATS |
1130 of.OfpCapabilities_OFPC_GROUP_STATS),
1131 },
1132 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301133}
1134
khenaidoo106c61a2021-08-11 18:05:46 -04001135// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001136func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001137 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001138 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001139 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001140 }
khenaidoo106c61a2021-08-11 18:05:46 -04001141 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001142}
1143
Neha Sharma96b7bf22020-06-15 10:37:32 +00001144func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001145 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 -07001146 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001147 var deviceID string
1148 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001149 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001150
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001151 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001152 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001153 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 -07001154 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1155 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001156
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001157 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301158
1159 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1160
Neha Sharma96b7bf22020-06-15 10:37:32 +00001161 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 -07001162 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001163
khenaidoodc2116e2021-10-19 17:33:19 -04001164 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001165 ParentId: dh.device.Id,
1166 OnuId: omciInd.OnuId,
1167 ParentPortNo: ponPort,
1168 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001169 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301170 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001171 "intf-id": omciInd.IntfId,
1172 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001173 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001174 deviceType = onuDevice.Type
1175 deviceID = onuDevice.Id
1176 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001177 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001178 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001179 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001180 } else {
1181 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001182 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 +05301183 deviceType = onuInCache.(*OnuDevice).deviceType
1184 deviceID = onuInCache.(*OnuDevice).deviceID
1185 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001186 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001187 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001188
khenaidoodc2116e2021-10-19 17:33:19 -04001189 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001190 ParentDeviceId: proxyDeviceID,
1191 ChildDeviceId: deviceID,
1192 Message: omciInd.Pkt,
1193 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301194 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001195 "source": dh.openOLT.config.AdapterEndpoint,
1196 "device-type": deviceType,
1197 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001198 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001199 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001200 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001201 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301202}
1203
khenaidoo106c61a2021-08-11 18:05:46 -04001204// //ProcessInterAdapterMessage sends the proxied messages to the target device
1205// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1206// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001207// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001208// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001209// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001210// return dh.handleInterAdapterOmciMsg(ctx, msg)
1211// }
1212// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1213// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001214
kesavandb9f54fd2021-11-25 20:08:04 +05301215// ProxyOmciRequests sends the proxied OMCI message to the target device
1216func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
1217 if omciMsgs.GetProxyAddress() == nil {
1218 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1219 if err != nil {
1220 return olterrors.NewErrNotFound("onu", log.Fields{
1221 "parent-device-id": dh.device.Id,
1222 "child-device-id": omciMsgs.ChildDeviceId}, err)
1223 }
1224 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1225 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1226 return olterrors.NewErrCommunication("send-failed", log.Fields{
1227 "parent-device-id": dh.device.Id,
1228 "child-device-id": omciMsgs.ChildDeviceId}, err)
1229 }
1230 } else {
1231 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1232 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1233 return olterrors.NewErrCommunication("send-failed", log.Fields{
1234 "parent-device-id": dh.device.Id,
1235 "child-device-id": omciMsgs.ChildDeviceId}, err)
1236 }
1237 }
1238 return nil
1239}
1240
1241func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1242 var intfID uint32
1243 var onuID uint32
1244 var connectStatus common.ConnectStatus_Types
1245 if onuDevice != nil {
1246 intfID = onuDevice.ProxyAddress.GetChannelId()
1247 onuID = onuDevice.ProxyAddress.GetOnuId()
1248 connectStatus = onuDevice.ConnectStatus
1249 } else {
1250 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1251 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1252 connectStatus = omciMsgs.GetConnectStatus()
1253 }
1254 if connectStatus != voltha.ConnectStatus_REACHABLE {
1255 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1256
1257 return olterrors.NewErrCommunication("unreachable", log.Fields{
1258 "intf-id": intfID,
1259 "onu-id": onuID}, nil)
1260 }
1261
1262 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1263 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1264
1265 onuSecOmciMsgList := omciMsgs.GetMessages()
1266
1267 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1268
1269 var omciMessage *oop.OmciMsg
1270 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1271 hex.Encode(hexPkt, onuSecOmciMsg)
1272 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1273
1274 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1275 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1276 //https://jira.opencord.org/browse/VOL-4604
1277 transid := extractOmciTransactionID(onuSecOmciMsg)
1278 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1279 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1280
1281 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1282 if err != nil {
1283 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1284 "intf-id": intfID,
1285 "onu-id": onuID,
1286 "message": omciMessage}, err)
1287 }
1288 }
1289 return nil
1290}
1291
khenaidoo106c61a2021-08-11 18:05:46 -04001292// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001293func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001294 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 -07001295
1296 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001297 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001298 if err != nil {
1299 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001300 "parent-device-id": dh.device.Id,
1301 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001302 }
khenaidoo106c61a2021-08-11 18:05:46 -04001303 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1304 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001305 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001306 "parent-device-id": dh.device.Id,
1307 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001308 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001309 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001310 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1311 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001312 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001313 "parent-device-id": dh.device.Id,
1314 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001315 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001316 }
1317 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301318}
1319
khenaidoodc2116e2021-10-19 17:33:19 -04001320func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001321 var intfID uint32
1322 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001323 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001324 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001325 intfID = onuDevice.ProxyAddress.GetChannelId()
1326 onuID = onuDevice.ProxyAddress.GetOnuId()
1327 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001328 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001329 intfID = omciMsg.GetProxyAddress().GetChannelId()
1330 onuID = omciMsg.GetProxyAddress().GetOnuId()
1331 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001332 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001333 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001334 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 -08001335
Thomas Lee S94109f12020-03-03 16:39:29 +05301336 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001337 "intf-id": intfID,
1338 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001339 }
1340
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001341 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1342 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301343 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001344 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001345 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1346 hex.Encode(hexPkt, omciMsg.Message)
1347 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1348
1349 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1350 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1351 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001352 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001353 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001354
Neha Sharma8f4e4322020-08-06 10:51:53 +00001355 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001356 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301357 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001358 "intf-id": intfID,
1359 "onu-id": onuID,
1360 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001363}
1364
David K. Bainbridge794735f2020-02-11 21:01:37 -08001365func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301366 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 +00001367 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001368 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001369 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001370 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301371 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301372 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001373 st, _ := status.FromError(err)
1374 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001375 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1376
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001377 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301378 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001379 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001380 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001381 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001382 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001384}
1385
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301386//getChildDevice function can be used in general to get child device, if not found in cache the function will
1387//get from core and update the cache and return the child device.
1388func (dh *DeviceHandler) getChildDevice(ctx context.Context, sn string, parentPortNo uint32) *OnuDevice {
1389 var InCacheOnuDev *OnuDevice
1390 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1391 if onuInCache.(*OnuDevice).serialNumber == sn {
1392 InCacheOnuDev = onuInCache.(*OnuDevice)
1393 return false
1394 }
1395 return true
1396 })
1397 //Got the onu device from cache return
1398 if InCacheOnuDev != nil {
1399 logger.Debugw(ctx, "Got child device from cache", log.Fields{"onudev": InCacheOnuDev.serialNumber})
1400 return InCacheOnuDev
1401 }
1402 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1403 ParentId: dh.device.Id,
1404 SerialNumber: sn,
1405 ParentPortNo: parentPortNo,
1406 })
1407 //No device found in core return nil
1408 if onuDevice == nil {
1409 return nil
1410 }
1411 onuID := onuDevice.ProxyAddress.OnuId
1412 intfID := plt.PortNoToIntfID(parentPortNo, voltha.Port_PON_OLT)
1413 onuKey := dh.formOnuKey(intfID, onuID)
1414
1415 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, intfID, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
1416 dh.onus.Store(onuKey, onuDev)
1417 logger.Debugw(ctx, "got child device from core", log.Fields{"onudev": onuDevice})
1418 return onuDev
1419}
1420
1421func (dh *DeviceHandler) checkForResourceExistance(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) (bool, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001422 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001423 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301424 tpInstExists := false
Matt Jeanneret53539512019-07-20 14:47:02 -04001425
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301426 //CheckOnuDevExistenceAtOnuDiscovery if true , a check will be made for the existence of the onu device. If the onu device
1427 // still exists , the onu discovery will be ignored, else a check for active techprofiles for ONU is checked.
1428 if !dh.openOLT.CheckOnuDevExistenceAtOnuDiscovery {
1429 onuDev := dh.getChildDevice(ctx, sn, parentPortNo)
1430 if onuDev != nil {
1431 var onuGemInfo *rsrcMgr.OnuGemInfo
1432 var err error
1433 if onuGemInfo, err = dh.resourceMgr[channelID].GetOnuGemInfo(ctx, onuDev.onuID); err != nil {
1434 logger.Warnw(ctx, "Unable to find onuGemInfo", log.Fields{"onuID": onuDev.onuID})
1435 return false, err
1436 }
1437 if onuGemInfo != nil {
1438 for _, uni := range onuGemInfo.UniPorts {
1439 uniID := plt.UniIDFromPortNum(uni)
1440 tpIDs := dh.resourceMgr[channelID].GetTechProfileIDForOnu(ctx, onuDev.onuID, uniID)
1441 if len(tpIDs) != 0 {
1442 logger.Warnw(ctx, "Techprofile present for ONU, ignoring onu discovery", log.Fields{"onuID": onuDev.onuID})
1443 tpInstExists = true
1444 break
1445 }
1446 }
1447 }
1448 }
1449 return tpInstExists, nil
1450 }
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301451
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301452 onuDevice, _ := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
1453 ParentId: dh.device.Id,
1454 SerialNumber: sn,
1455 ParentPortNo: parentPortNo,
1456 })
1457 if onuDevice != nil {
1458 logger.Infow(ctx, "Child device still present ignoring discovery indication", log.Fields{"sn": sn})
1459 return true, nil
1460 }
1461 logger.Infow(ctx, "No device present in core , continuing with discovery", log.Fields{"sn": sn})
1462
1463 return false, nil
1464
1465}
1466
1467func (dh *DeviceHandler) processDiscONULOSClear(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) bool {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301468 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001469 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001470 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301471
1472 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1473 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1474 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1475 OnuLosRaise event sent for it */
1476 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1477 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1478 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001479 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301480 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1481 "currentIntfId": onuDiscInd.GetIntfId()})
1482 // TODO:: Should we need to ignore raising OnuLosClear event
1483 // when onu connected to different PON?
1484 }
1485 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1486 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1487 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001488 go func() {
1489 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001490 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001491 }
1492 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301493 }
1494 return true
1495 })
1496
Neha Sharma96b7bf22020-06-15 10:37:32 +00001497 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301498 return true
1499 }
1500 return false
1501}
1502
1503func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
1504 channelID := onuDiscInd.GetIntfId()
1505 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
1506
1507 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
1508 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
1509
1510 tpInstExists, errtp := dh.checkForResourceExistance(ctx, onuDiscInd, sn)
1511 if errtp != nil {
1512 return errtp
1513 }
1514 if tpInstExists {
1515 //ignore the discovery if tpinstance is present.
David K. Bainbridge794735f2020-02-11 21:01:37 -08001516 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001517 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05301518 if onuBeingProcessed := dh.processDiscONULOSClear(ctx, onuDiscInd, sn); onuBeingProcessed {
1519 return nil
1520 }
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001521 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001522
1523 // check the ONU is already know to the OLT
1524 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001525 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001526 ParentId: dh.device.Id,
1527 SerialNumber: sn,
1528 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001529
1530 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001531 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 -08001532 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001533 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 -08001534 switch e.Code() {
1535 case codes.Internal:
1536 // this probably means NOT FOUND, so just create a new device
1537 onuDevice = nil
1538 case codes.DeadlineExceeded:
1539 // if the call times out, cleanup and exit
1540 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001541 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001542 }
1543 }
1544 }
1545
1546 if onuDevice == nil {
1547 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001548 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001549 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001550 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001551 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001552
Neha Sharma96b7bf22020-06-15 10:37:32 +00001553 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001554
1555 if err != nil {
1556 // if we can't create an ID in resource manager,
1557 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001558 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001559 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001560 "pon-intf-id": ponintfid,
1561 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001562 }
1563
khenaidoodc2116e2021-10-19 17:33:19 -04001564 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001565 ParentId: dh.device.Id,
1566 ParentPortNo: parentPortNo,
1567 ChannelId: channelID,
1568 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1569 SerialNumber: sn,
1570 OnuId: onuID,
1571 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001572 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001573 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 +05301574 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001575 "pon-intf-id": ponintfid,
1576 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001577 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001578 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 -07001579 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001580 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001581 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301582 log.Fields{"onuDevice": onuDevice,
1583 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001584 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301585 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001586 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001587
khenaidoo106c61a2021-08-11 18:05:46 -04001588 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1589 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1590 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1591 cancel()
1592 if err != nil {
1593 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1594 }
1595
Matteo Scandolo945e4012019-12-12 14:16:11 -08001596 // we can now use the existing ONU Id
1597 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001598 //Insert the ONU into cache to use in OnuIndication.
1599 //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 +00001600 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001601 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301602 "intfId": onuDiscInd.GetIntfId(),
1603 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001604 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001605
khenaidoo106c61a2021-08-11 18:05:46 -04001606 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301607 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001608 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301609 log.Fields{"onu": onuDev,
1610 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001611
khenaidoodc2116e2021-10-19 17:33:19 -04001612 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001613 DeviceId: onuDevice.Id,
1614 ParentDeviceId: dh.device.Id,
1615 OperStatus: common.OperStatus_DISCOVERED,
1616 ConnStatus: common.ConnectStatus_REACHABLE,
1617 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301618 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001619 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001620 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001621 }
khenaidoo106c61a2021-08-11 18:05:46 -04001622
Neha Sharma96b7bf22020-06-15 10:37:32 +00001623 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001624 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301625 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001626 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001627 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001628 }
1629 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001630}
1631
Mahir Gunyelb0046752021-02-26 13:51:05 -08001632func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001633
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001634 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001635 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001636 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001637 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001638 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301639 log.Fields{"onuId": onuInd.OnuId,
1640 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301641 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001642 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001643 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301644
David K. Bainbridge794735f2020-02-11 21:01:37 -08001645 errFields := log.Fields{"device-id": dh.device.Id}
1646
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301647 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1648
Mahir Gunyele77977b2019-06-27 05:36:22 -07001649 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1650 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001651 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001652 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001653 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001654 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1655 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001656 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001657 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001658 errFields["onu-id"] = onuInd.OnuId
1659 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001660 }
khenaidoodc2116e2021-10-19 17:33:19 -04001661 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001662 ParentId: dh.device.Id,
1663 SerialNumber: serialNumber,
1664 OnuId: onuInd.OnuId,
1665 ParentPortNo: ponPort,
1666 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001667 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001668
David K. Bainbridge794735f2020-02-11 21:01:37 -08001669 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001670 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001671 }
1672
David K. Bainbridge794735f2020-02-11 21:01:37 -08001673 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001674 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001675 "previousIntfId": onuDevice.ParentPortNo,
1676 "currentIntfId": ponPort})
1677 }
1678
1679 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001680 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301681 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1682 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301683 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001684 }
1685 if !foundInCache {
1686 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1687
khenaidoo106c61a2021-08-11 18:05:46 -04001688 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 -08001689
1690 }
kesavand7cf3a052020-08-28 12:49:18 +05301691 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001692 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001693 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301694 }
1695 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001696 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001697 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001698 }
1699 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001700}
1701
Neha Sharma96b7bf22020-06-15 10:37:32 +00001702func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001703 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 -07001704 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1705 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1706 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1707 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001708 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001709 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1710 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001711 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001712 onuInd.OperState = "down"
1713 }
1714 }
1715
David K. Bainbridge794735f2020-02-11 21:01:37 -08001716 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001717 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001718 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 -04001719
khenaidoodc2116e2021-10-19 17:33:19 -04001720 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001721 DeviceId: onuDevice.Id,
1722 OnuIndication: onuInd,
1723 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001724 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301725 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001726 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001727 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001728 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001729 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001730 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001731 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001732 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001733 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001734 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001735}
1736
cuilin20187b2a8c32019-03-26 19:52:28 -07001737func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1738 if serialNum != nil {
1739 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001740 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001741 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001742}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001743func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1744 decodedStr, err := hex.DecodeString(serialNum[4:])
1745 if err != nil {
1746 return nil, err
1747 }
1748 return &oop.SerialNumber{
1749 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001750 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001751 }, nil
1752}
cuilin20187b2a8c32019-03-26 19:52:28 -07001753
1754func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001755 if len(vendorSpecific) > 3 {
1756 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1757 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1758 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1759 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1760 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1761 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1762 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1763 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1764 return tmp
1765 }
1766 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001767}
1768
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001769//UpdateFlowsBulk upates the bulk flow
1770func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301771 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001772}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001773
1774//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001775func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1776 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301777 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001778 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301779 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001780
khenaidoodc2116e2021-10-19 17:33:19 -04001781 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001782 ParentId: dh.device.Id,
1783 OnuId: onuID,
1784 ParentPortNo: parentPort,
1785 })
1786
Girish Gowdru0c588b22019-04-23 23:24:56 -04001787 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001788 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001789 "intf-id": parentPort,
1790 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001791 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001792 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 -08001793 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301794}
1795
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001796// SendPacketInToCore sends packet-in to core
1797// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1798// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001799func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001800 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001801 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001802 "port": logicalPort,
1803 "packet": hex.EncodeToString(packetPayload),
1804 "device-id": dh.device.Id,
1805 })
1806 }
khenaidoo106c61a2021-08-11 18:05:46 -04001807
khenaidoodc2116e2021-10-19 17:33:19 -04001808 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001809 DeviceId: dh.device.Id,
1810 Port: logicalPort,
1811 Packet: packetPayload,
1812 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301813 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001814 "source": "adapter",
1815 "destination": "core",
1816 "device-id": dh.device.Id,
1817 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001818 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001819 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001820 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001821 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001822 "packet": hex.EncodeToString(packetPayload),
1823 "device-id": dh.device.Id,
1824 })
1825 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001826 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001827}
1828
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001829// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001831 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001832
1833 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1834 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001836 }
1837
Kent Hagermane6ff1012020-07-14 15:07:53 -04001838 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001839 metrics := dh.metrics.GetSubscriberMetrics()
1840 for _, m := range pmConfigs.Metrics {
1841 metrics[m.Name].Enabled = m.Enabled
1842
1843 }
1844 }
1845}
1846
khenaidoodc2116e2021-10-19 17:33:19 -04001847func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001848 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001849 var errorsList []error
1850
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001851 if dh.getDeviceDeletionInProgressFlag() {
1852 // The device itself is going to be reset as part of deletion. So nothing to be done.
1853 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1854 return nil
1855 }
1856
Girish Gowdru0c588b22019-04-23 23:24:56 -04001857 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001858 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001859 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001860
Neha Sharma96b7bf22020-06-15 10:37:32 +00001861 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301862 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001863 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301864 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001865 if flow_utils.HasGroup(flow) {
1866 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1867 } else {
yasin saplid0566272021-12-21 09:10:30 +00001868 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
Girish Gowdra491a9c62021-01-06 16:43:07 -08001869 }
Girish Gowdracefae192020-03-19 18:14:10 -07001870 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01001871 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
1872 //The flow we want to remove is not there, there is no need to throw an error
1873 logger.Warnw(ctx, "flow-to-remove-not-found",
1874 log.Fields{
1875 "ponIf": intfID,
1876 "flowToRemove": flow,
1877 "error": err,
1878 })
1879 } else {
1880 errorsList = append(errorsList, err)
1881 }
Girish Gowdracefae192020-03-19 18:14:10 -07001882 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001883 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301884
1885 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00001886 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001887 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301888 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001889 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301890 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001891 if flow_utils.HasGroup(flow) {
1892 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1893 } else {
yasin saplid0566272021-12-21 09:10:30 +00001894 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001895 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1896 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1897 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1898 } else {
yasin saplid0566272021-12-21 09:10:30 +00001899 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001900 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001901 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001902 if err != nil {
1903 errorsList = append(errorsList, err)
1904 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301905 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001906 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001907
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001908 return errorsList
1909}
1910
1911func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1912 var err error
1913 var errorsList []error
1914
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001915 if dh.getDeviceDeletionInProgressFlag() {
1916 // The device itself is going to be reset as part of deletion. So nothing to be done.
1917 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1918 return nil
1919 }
1920
Girish Gowdracefae192020-03-19 18:14:10 -07001921 // 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 +00001922 if groups != nil {
1923 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001924 // err = dh.groupMgr.AddGroup(ctx, group)
1925 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001926 if err != nil {
1927 errorsList = append(errorsList, err)
1928 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001929 }
1930 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001931 // err = dh.groupMgr.ModifyGroup(ctx, group)
1932 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001933 if err != nil {
1934 errorsList = append(errorsList, err)
1935 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001936 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001937 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001938 // err = dh.groupMgr.DeleteGroup(ctx, group)
1939 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001940 if err != nil {
1941 errorsList = append(errorsList, err)
1942 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001943 }
1944 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001945
1946 return errorsList
1947}
1948
1949//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001950func (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 -07001951
1952 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001953
1954 if dh.getDeviceDeletionInProgressFlag() {
1955 // The device itself is going to be reset as part of deletion. So nothing to be done.
1956 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1957 return nil
1958 }
1959
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001960 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1961 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1962 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001963 if len(errorsList) > 0 {
1964 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1965 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001966 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001967 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301968}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001969
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001970//DisableDevice disables the given device
1971//It marks the following for the given device:
1972//Device-Handler Admin-State : down
1973//Device Port-State: UNKNOWN
1974//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001975func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001976 /* On device disable ,admin state update has to be done prior sending request to agent since
1977 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001978 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001979 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001980 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001981 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001982 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001983 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001984 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001985 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001986 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001987 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301988
1989 dh.discOnus = sync.Map{}
1990 dh.onus = sync.Map{}
1991
Thomas Lee S85f37312020-04-03 17:06:12 +05301992 //stopping the stats collector
1993 dh.stopCollector <- true
1994
Neha Sharma96b7bf22020-06-15 10:37:32 +00001995 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001996 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301997 //Update device Admin state
1998 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001999
kdarapu1afeceb2020-02-12 01:38:09 -05002000 // 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 -04002001 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002002 DeviceId: cloned.Id,
2003 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
2004 OperStatus: voltha.OperStatus_UNKNOWN,
2005 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002006 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002007 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002008 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002009 return nil
2010}
2011
Neha Sharma96b7bf22020-06-15 10:37:32 +00002012func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002013 // Update onu state as unreachable in onu adapter
2014 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302015 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04002016
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002017 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04002018 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002019 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002020 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 -04002021 }
2022 if onuDevices != nil {
2023 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04002024 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002025 DeviceId: onuDevice.Id,
2026 OnuIndication: &onuInd,
2027 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002028 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002029 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04002030 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04002031 }
2032
2033 }
2034 }
2035
2036}
2037
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002038//ReenableDevice re-enables the olt device after disable
2039//It marks the following for the given device:
2040//Device-Handler Admin-State : up
2041//Device Port-State: ACTIVE
2042//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00002043func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002044 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302045 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00002046 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05302047 }
2048 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002049 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002050
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002051 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04002052 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002053 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002054 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002055 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
2056 } else {
2057 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
2058 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
2059 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002060 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002061 if retError == nil {
2062 //Update the device oper status as ACTIVE
2063 device.OperStatus = voltha.OperStatus_ACTIVE
2064 } else {
2065 //Update the device oper status as FAILED
2066 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002067 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002068 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002069
khenaidoodc2116e2021-10-19 17:33:19 -04002070 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002071 DeviceId: device.Id,
2072 OperStatus: device.OperStatus,
2073 ConnStatus: device.ConnectStatus,
2074 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302075 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002076 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002077 "connect-status": device.ConnectStatus,
2078 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002079 }
kesavand39e0aa32020-01-28 20:58:50 -05002080
Neha Sharma96b7bf22020-06-15 10:37:32 +00002081 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002082
Mahir Gunyele5e807a2021-10-22 11:33:25 -07002083 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04002084}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002085
npujarec5762e2020-01-01 14:08:48 +05302086func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04002087 var uniID uint32
2088 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302089 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002090 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002091 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00002092 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002093 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002094 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002095 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002096 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002097 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002098 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00002099 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002100 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00002101 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002102 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002103 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002104 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00002105 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002106 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302107 }
yasin saplibddc2d72022-02-08 13:10:17 +00002108 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
2109 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002110 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302111 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002112 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002113 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002114 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 +00002115 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002116 }
2117 return nil
2118}
2119
Devmalya Paul495b94a2019-08-27 19:42:00 -04002120// 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 +05302121func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002122 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002123 /* Clear the KV store data associated with the all the UNI ports
2124 This clears up flow data and also resource map data for various
2125 other pon resources like alloc_id and gemport_id
2126 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002127
2128 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002129 var wg sync.WaitGroup
2130 wg.Add(1) // for the mcast routine below to finish
2131 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2132 for _, flMgr := range dh.flowMgr {
2133 wg.Add(1) // for the flow handler routine below to finish
2134 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2135 }
2136 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2137 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2138 } else {
2139 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2140 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002141
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002142 dh.cleanupDeviceResources(ctx)
2143 logger.Debugw(ctx, "removed-device-from-Resource-manager-KV-store", log.Fields{"device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002144 // Stop the Stats collector
2145 dh.stopCollector <- true
2146 // stop the heartbeat check routine
2147 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05302148 dh.lockDevice.RLock()
2149 // Stop the read indication only if it the routine is active
2150 if dh.isReadIndicationRoutineActive {
2151 dh.stopIndications <- true
2152 }
2153 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002154 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002155 //Reset the state
2156 if dh.Client != nil {
2157 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302158 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002159 }
2160 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002161 // There is no need to update the core about operation status and connection status of the OLT.
2162 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2163 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2164 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002165
khenaidoo7eb2d672021-10-22 19:08:50 -04002166 // Stop the adapter grpc clients for that parent device
2167 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002168 return nil
2169}
Kent Hagermane6ff1012020-07-14 15:07:53 -04002170func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002171
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002172 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302173 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002174 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002175 var err error
yasin sapli9e4c5092022-02-01 13:52:33 +00002176 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002177 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002178 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002179 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002180 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302181 }
2182 }
yasin saplibddc2d72022-02-08 13:10:17 +00002183 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx)
2184 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002185 dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002186 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2187 logger.Debug(ctx, err)
2188 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002189 }
yasin saplibddc2d72022-02-08 13:10:17 +00002190 // Clean up NNI manager's data
2191 _ = dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002192 }
A R Karthick1f85b802019-10-11 05:06:05 +00002193
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002194 // Take one final sweep at cleaning up KV store for the OLT device
2195 // Clean everything at <base-path-prefix>/openolt/<device-id>
2196 kvClient, err := kvstore.NewEtcdClient(ctx, dh.openOLT.KVStoreAddress, rsrcMgr.KvstoreTimeout, log.FatalLevel)
2197 if err == nil {
2198 kvBackend := &db.Backend{
2199 Client: kvClient,
2200 StoreType: dh.openOLT.KVStoreType,
2201 Address: dh.openOLT.KVStoreAddress,
2202 Timeout: rsrcMgr.KvstoreTimeout,
2203 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, dh.cm.Backend.PathPrefix, dh.device.Id)}
2204 _ = kvBackend.DeleteWithPrefix(ctx, "")
2205 }
2206
Devmalya Paul495b94a2019-08-27 19:42:00 -04002207 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302208 dh.onus.Range(func(key interface{}, value interface{}) bool {
2209 dh.onus.Delete(key)
2210 return true
2211 })
2212
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002213 /*Delete discovered ONU map for the device*/
2214 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2215 dh.discOnus.Delete(key)
2216 return true
2217 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002218}
2219
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002220//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002221func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002222 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302223 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002224 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002225 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002226 return nil
2227}
2228
David K. Bainbridge794735f2020-02-11 21:01:37 -08002229func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002230 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002231 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002232 "packet-indication": *packetIn,
2233 "device-id": dh.device.Id,
2234 "packet": hex.EncodeToString(packetIn.Pkt),
2235 })
2236 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002237 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002238 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002239 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002240 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002241 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002242 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002243 "logical-port-num": logicalPortNum,
2244 "device-id": dh.device.Id,
2245 "packet": hex.EncodeToString(packetIn.Pkt),
2246 })
2247 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002248
khenaidoodc2116e2021-10-19 17:33:19 -04002249 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002250 DeviceId: dh.device.Id,
2251 Port: logicalPortNum,
2252 Packet: packetIn.Pkt,
2253 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302254 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002255 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302256 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002257 "device-id": dh.device.Id,
2258 "packet": hex.EncodeToString(packetIn.Pkt),
2259 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002260 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002261
Matteo Scandolo92186242020-06-12 10:54:18 -07002262 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002263 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002264 "packet": hex.EncodeToString(packetIn.Pkt),
2265 "device-id": dh.device.Id,
2266 })
2267 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002268 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002269}
2270
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002271// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002272func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002273 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002275 "device-id": dh.device.Id,
2276 "egress-port-no": egressPortNo,
2277 "pkt-length": len(packet.Data),
2278 "packet": hex.EncodeToString(packet.Data),
2279 })
2280 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002281
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002282 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002283 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002284 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2285 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302286 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2287 // Do not packet-out lldp packets on uni port.
2288 // ONOS has no clue about uni/nni ports, it just packets out on all
2289 // available ports on the Logical Switch. It should not be interested
2290 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002291 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002292 "device-id": dh.device.Id,
2293 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302294 return nil
2295 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002296 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2297 if innerEthType == 0x8100 {
2298 // q-in-q 802.1ad or 802.1q double tagged packet.
2299 // slice out the outer tag.
2300 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002301 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002302 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002303 "packet-data": hex.EncodeToString(packet.Data),
2304 "device-id": dh.device.Id,
2305 })
2306 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002307 }
2308 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002309 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2310 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2311 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002312
Girish Gowdra9602eb42020-09-09 15:50:39 -07002313 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002314 if err != nil {
2315 // In this case the openolt agent will receive the gemPortID as 0.
2316 // The agent tries to retrieve the gemPortID in this case.
2317 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002319 "intf-id": intfID,
2320 "onu-id": onuID,
2321 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002322 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302323 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002324 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002325 }
2326
2327 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002328 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002330 "egress-port-no": egressPortNo,
2331 "intf-id": intfID,
2332 "onu-id": onuID,
2333 "uni-id": uniID,
2334 "gem-port-id": gemPortID,
2335 "packet": hex.EncodeToString(packet.Data),
2336 "device-id": dh.device.Id,
2337 })
2338 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002339
npujarec5762e2020-01-01 14:08:48 +05302340 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302341 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002342 "source": "adapter",
2343 "destination": "onu",
2344 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002345 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002346 "oni-id": onuID,
2347 "uni-id": uniID,
2348 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002349 "packet": hex.EncodeToString(packet.Data),
2350 "device-id": dh.device.Id,
2351 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002352 }
2353 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002354 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002355 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002356 return olterrors.NewErrInvalidValue(log.Fields{
2357 "egress-nni-port": egressPortNo,
2358 "device-id": dh.device.Id,
2359 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002360 }
2361 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002362
Matteo Scandolo92186242020-06-12 10:54:18 -07002363 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002364 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002365 "uplink-pkt": uplinkPkt,
2366 "packet": hex.EncodeToString(packet.Data),
2367 "device-id": dh.device.Id,
2368 })
2369 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002370
npujarec5762e2020-01-01 14:08:48 +05302371 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002372 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2373 "packet": hex.EncodeToString(packet.Data),
2374 "device-id": dh.device.Id,
2375 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002376 }
2377 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002378 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302379 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002380 "egressPortType": egressPortType,
2381 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302382 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002383 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002384 }
2385 return nil
2386}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002387
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002388func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2389 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002390}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302391
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002392func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002393
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302394 // start the heartbeat check towards the OLT.
2395 var timerCheck *time.Timer
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302396 dh.heartbeatSignature = dh.getHeartbeatSignature(ctx)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302397
2398 for {
2399 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2400 select {
2401 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002402 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002403 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002404 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302405 if timerCheck == nil {
2406 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002407 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302408 }
2409 } else {
2410 if timerCheck != nil {
2411 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002412 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302413 }
2414 timerCheck = nil
2415 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302416 if dh.heartbeatSignature == 0 || dh.heartbeatSignature == heartBeat.HeartbeatSignature {
2417 if dh.heartbeatSignature == 0 {
2418 // First time the signature will be 0, update the signture to DB when not found.
2419 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2420 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2421 }
2422 logger.Infow(ctx, "heartbeat signature", log.Fields{"sign": dh.heartbeatSignature})
2423
2424 dh.lockDevice.RLock()
2425 // Stop the read indication only if it the routine is active
2426 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2427 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2428 // on next execution of the readIndication routine.
2429 if !dh.isReadIndicationRoutineActive {
2430 // Start reading indications
2431 go func() {
2432 if err = dh.readIndications(ctx); err != nil {
2433 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2434 }
2435 }()
2436 }
2437 dh.lockDevice.RUnlock()
2438
2439 } else {
2440 logger.Warn(ctx, "Heartbeat signature changed, OLT is rebooted. Cleaningup resources.")
2441 dh.updateHeartbeatSignature(ctx, heartBeat.HeartbeatSignature)
2442 dh.heartbeatSignature = heartBeat.HeartbeatSignature
2443 go dh.updateStateRebooted(ctx)
2444 }
2445
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302446 }
2447 cancel()
2448 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002449 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302450 return
2451 }
2452 }
2453}
2454
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002455func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002456 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002457 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002458 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2459 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2460 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2461 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2462 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002463 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002464 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2465 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002466 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302467
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302468 logger.Warnw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002469 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002470 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002471 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002472 DeviceId: dh.device.Id,
2473 OperStatus: voltha.OperStatus_UNKNOWN,
2474 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2475 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002476 _ = 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 -04002477 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302478 /*
2479 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
2480 DeviceId: dh.device.Id,
2481 PortTypeFilter: 0,
2482 OperStatus: voltha.OperStatus_UNKNOWN,
2483 }); err != nil {
2484 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
2485 }
2486 */
Gamze Abaka07868a52020-12-17 14:19:28 +00002487
2488 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002489 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002490 cloned := proto.Clone(device).(*voltha.Device)
2491 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2492 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2493 dh.device = cloned // update local copy of the device
2494 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002495
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002496 // Stop the Stats collector
2497 dh.stopCollector <- true
2498 // stop the heartbeat check routine
2499 dh.stopHeartbeatCheck <- true
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002500 dh.lockDevice.RLock()
2501 // Stop the read indication only if it the routine is active
2502 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2503 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2504 // on next execution of the readIndication routine.
2505 if dh.isReadIndicationRoutineActive {
2506 dh.stopIndications <- true
2507 }
2508 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002509 dh.transitionMap.Handle(ctx, DeviceInit)
2510
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302511 }
2512}
kesavand39e0aa32020-01-28 20:58:50 -05002513
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302514func (dh *DeviceHandler) updateStateRebooted(ctx context.Context) {
2515 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
2516 if err != nil || device == nil {
2517 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2518 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2519 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2520 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2521 // cleanup in the adapter was already done during DeleteDevice API handler routine.
2522 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
2523 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2524 return
2525 }
2526
2527 logger.Warnw(ctx, "update-state-rebooted", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2528 "admin-state": device.AdminState, "oper-status": device.OperStatus, "conn-status": voltha.ConnectStatus_UNREACHABLE})
2529 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
2530 DeviceId: dh.device.Id,
2531 OperStatus: voltha.OperStatus_REBOOTED,
2532 ConnStatus: voltha.ConnectStatus_REACHABLE,
2533 }); err != nil {
2534 _ = olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
2535 }
2536
2537 dh.lockDevice.RLock()
2538 // Stop the read indication only if it the routine is active
2539 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2540 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2541 // on next execution of the readIndication routine.
2542 if dh.isReadIndicationRoutineActive {
2543 dh.stopIndications <- true
2544 }
2545 dh.lockDevice.RUnlock()
2546
2547 //raise olt communication failure event
2548 raisedTs := time.Now().Unix()
2549 cloned := proto.Clone(device).(*voltha.Device)
2550 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2551 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2552 dh.device = cloned // update local copy of the device
2553 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
2554
2555 dh.cleanupDeviceResources(ctx)
2556 // Stop the Stats collector
2557 dh.stopCollector <- true
2558 // stop the heartbeat check routine
2559 dh.stopHeartbeatCheck <- true
2560
2561 var wg sync.WaitGroup
2562 wg.Add(1) // for the multicast handler routine
2563 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2564 for _, flMgr := range dh.flowMgr {
2565 wg.Add(1) // for the flow handler routine
2566 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2567 }
2568 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2569 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2570 } else {
2571 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2572 }
2573
2574 //reset adapter reconcile flag
2575 dh.adapterPreviouslyConnected = false
2576 for {
2577
2578 childDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
2579 if err != nil || childDevices == nil {
2580 logger.Errorw(ctx, "Failed to get child devices from core", log.Fields{"deviceID": dh.device.Id})
2581 continue
2582 }
2583 if len(childDevices.Items) == 0 {
2584 logger.Infow(ctx, "All childDevices cleared from core, proceed with device init", log.Fields{"deviceID": dh.device.Id})
2585 break
2586 } else {
2587 logger.Warn(ctx, "Not all child devices are cleared, continuing to wait")
2588 time.Sleep(5 * time.Second)
2589 }
2590
2591 }
2592 logger.Infow(ctx, "cleanup complete after reboot , moving to init", log.Fields{"deviceID": device.Id})
2593 dh.transitionMap.Handle(ctx, DeviceInit)
2594
2595}
2596
kesavand39e0aa32020-01-28 20:58:50 -05002597// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002598func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2599 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2600 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002601}
2602
2603// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002604func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2605 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2606 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002607}
2608
kdarapu1afeceb2020-02-12 01:38:09 -05002609//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 +00002610func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2611 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002612 if port.GetType() == voltha.Port_ETHERNET_NNI {
2613 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002614 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302615 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302616 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002617 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002618 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002619 }
2620 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002621 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002622 ponIntf := &oop.Interface{IntfId: ponID}
2623 var operStatus voltha.OperStatus_Types
2624 if enablePort {
2625 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302626 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002627
2628 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302629 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002630 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002631 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002632 }
2633 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002634 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002635 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002636 } else {
2637 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302638 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002639 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302640 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002641 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002642 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002643 }
2644 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002645 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002646 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002647 }
khenaidoodc2116e2021-10-19 17:33:19 -04002648 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002649 DeviceId: dh.device.Id,
2650 PortType: voltha.Port_PON_OLT,
2651 PortNo: port.PortNo,
2652 OperStatus: operStatus,
2653 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302654 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302655 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002656 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002657 }
2658 return nil
2659}
2660
kdarapu1afeceb2020-02-12 01:38:09 -05002661//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002662func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002663 // Disable the port and update the oper_port_status to core
2664 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002665 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002666 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002667 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302668 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302669 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002670 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002671 }
2672 }
2673 }
2674 return nil
2675}
2676
2677//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002678func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2679 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2680 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002681 if port.Type == voltha.Port_ETHERNET_NNI {
2682 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002683 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002684 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002685 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002686 }
2687 }
2688 if port.Type == voltha.Port_PON_OLT {
2689 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002690 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002691 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002692 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002693 }
2694 }
2695 }
2696}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002697
2698// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002699func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002700 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07002701 if dh.getDeviceDeletionInProgressFlag() {
2702 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
2703 // will reboot, so everything will be reset on the pOLT too.
2704 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
2705 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
2706 return nil
2707 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002708 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002709 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002710
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002711 var sn *oop.SerialNumber
2712 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002713 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302714 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002715 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302716 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002717 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002718 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002719
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002720 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002721 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00002722 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002723 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2724 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2725 "device-id": dh.device.Id,
2726 "intf-id": intfID,
2727 "onuID": onuID,
2728 "err": err})
2729 } else {
2730 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00002731 // Delete flows from device before schedulers and queue
2732 // Clear flowids for gem cache.
2733 removedFlows := []uint64{}
2734 for _, gem := range onuGem.GemPorts {
2735 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
2736 for _, flowID := range flowIDs {
2737 //multiple gem port can have the same flow id
2738 //it is better to send only one flowRemove request to the agent
2739 var alreadyRemoved bool
2740 for _, removedFlowID := range removedFlows {
2741 if removedFlowID == flowID {
2742 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
2743 alreadyRemoved = true
2744 break
2745 }
2746 }
2747 if !alreadyRemoved {
2748 flow := &oop.Flow{FlowId: flowID}
2749 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
2750 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
2751 "device-id": dh.device.Id,
2752 "onu-device": onu,
2753 "err": err})
2754 }
2755 removedFlows = appendUnique64bit(removedFlows, flowID)
2756 }
2757 }
2758 }
2759 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
2760 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002761 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2762 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2763 "device-id": dh.device.Id,
2764 "onu-device": onu,
2765 "err": err})
2766 }
yasin saplibddc2d72022-02-08 13:10:17 +00002767 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002768 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2769 "intf-id": intfID,
2770 "onu-device": onu,
2771 "onu-gem": onuGem,
2772 "err": err})
2773 //Not returning error on cleanup.
2774 }
2775 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302776
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002777 }
yasin saplibddc2d72022-02-08 13:10:17 +00002778 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002779 dh.onus.Delete(onuKey)
2780 dh.discOnus.Delete(onuSn)
2781
2782 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002783 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302784 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302785 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002786 "onu-id": onuID}, err).Log()
2787 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002788
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002789 return nil
2790}
Girish Gowdracefae192020-03-19 18:14:10 -07002791
2792func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002793 for _, field := range flow_utils.GetOfbFields(flow) {
2794 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002795 return field.GetPort()
2796 }
2797 }
2798 return InvalidPort
2799}
2800
2801func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002802 for _, action := range flow_utils.GetActions(flow) {
2803 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002804 if out := action.GetOutput(); out != nil {
2805 return out.GetPort()
2806 }
2807 }
2808 }
2809 return InvalidPort
2810}
2811
Girish Gowdracefae192020-03-19 18:14:10 -07002812func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2813 inPort := getInPortFromFlow(flow)
2814 outPort := getOutPortFromFlow(flow)
2815
2816 if inPort == InvalidPort || outPort == InvalidPort {
2817 return inPort, outPort
2818 }
2819
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002820 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002821 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002822 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002823 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002824 return uniPort, outPort
2825 }
2826 }
2827 } else {
2828 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002829 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002830 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002831 return inPort, uniPort
2832 }
2833 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002834 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002835 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002836 return uniPort, outPort
2837 }
2838 }
2839 }
2840
2841 return InvalidPort, InvalidPort
2842}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002843
2844func extractOmciTransactionID(omciPkt []byte) uint16 {
2845 if len(omciPkt) > 3 {
2846 d := omciPkt[0:2]
2847 transid := binary.BigEndian.Uint16(d)
2848 return transid
2849 }
2850 return 0
2851}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002852
2853// StoreOnuDevice stores the onu parameters to the local cache.
2854func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2855 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2856 dh.onus.Store(onuKey, onuDevice)
2857}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002858
khenaidoodc2116e2021-10-19 17:33:19 -04002859func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002860 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002861 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002862 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002863 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002864 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002865 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002866 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002867 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2868 return nil, err
2869 }
2870 ID = device.ProxyAddress.GetOnuId()
2871 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2872 valueparam.Onu = &Onu
2873 valueparam.Value = value
2874
2875 // This API is unsupported until agent patch is added
2876 resp.Unsupported = uint32(value)
2877 _ = ctx
2878
2879 // Uncomment this code once agent changes are complete and tests
2880 /*
2881 resp, err = dh.Client.GetValue(ctx, valueparam)
2882 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002883 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002884 return nil, err
2885 }
2886 */
2887
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002888 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 -08002889 return resp, nil
2890}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002891
yasin saplid0566272021-12-21 09:10:30 +00002892func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
2893 // Default to NNI
2894 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07002895 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002896 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002897 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002898 }
2899 return intfID
2900}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002901
Mahir Gunyelb0046752021-02-26 13:51:05 -08002902func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2903 dh.perPonOnuIndicationChannelLock.Lock()
2904 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2905 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002906 return ch.indicationChannel
2907 }
2908 channels := onuIndicationChannels{
2909 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002910 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002911 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002912 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002913 stopChannel: make(chan struct{}),
2914 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002915 dh.perPonOnuIndicationChannel[intfID] = channels
2916 dh.perPonOnuIndicationChannelLock.Unlock()
2917 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002918 return channels.indicationChannel
2919
2920}
2921
Mahir Gunyelb0046752021-02-26 13:51:05 -08002922func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2923 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2924 dh.perPonOnuIndicationChannelLock.Lock()
2925 defer dh.perPonOnuIndicationChannelLock.Unlock()
2926 for _, v := range dh.perPonOnuIndicationChannel {
2927 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002928 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002929 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002930}
2931
Mahir Gunyelb0046752021-02-26 13:51:05 -08002932func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2933 ind := onuIndicationMsg{
2934 ctx: ctx,
2935 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002936 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002937 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002938 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002939 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002940}
2941
Mahir Gunyelb0046752021-02-26 13:51:05 -08002942func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002943 for {
2944 select {
2945 // process one indication per onu, before proceeding to the next one
2946 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08002947 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002948 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08002949 "ind": indication})
2950 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002951 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002952 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002953 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2954 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002955 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002956 }
2957 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002958 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002959 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2960 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002961 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002962 }
2963 }
2964 case <-onuChannels.stopChannel:
2965 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2966 close(onuChannels.indicationChannel)
2967 return
2968 }
2969 }
2970}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002971
2972// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2973// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04002974func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002975 if dh.getDeviceDeletionInProgressFlag() {
2976 // The device itself is going to be reset as part of deletion. So nothing to be done.
2977 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2978 return nil
2979 }
2980
Girish Gowdra491a9c62021-01-06 16:43:07 -08002981 // Step1 : Fill McastFlowOrGroupControlBlock
2982 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2983 // Step3 : Wait on response channel for response
2984 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002985 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002986 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2987 errChan := make(chan error)
2988 var groupID uint32
2989 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2990 ctx: ctx,
2991 flowOrGroupAction: action,
2992 flow: flow,
2993 group: group,
2994 errChan: &errChan,
2995 }
2996 if flow != nil {
2997 groupID = flow_utils.GetGroup(flow)
2998 } else if group != nil {
2999 groupID = group.Desc.GroupId
3000 } else {
3001 return errors.New("flow-and-group-both-nil")
3002 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003003 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
3004 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
3005 // Derive the appropriate go routine to handle the request by a simple module operation.
3006 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
3007 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
3008 // Wait for handler to return error value
3009 err := <-errChan
3010 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
3011 return err
3012 }
3013 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
3014 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08003015}
3016
3017// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003018func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003019 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003020 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08003021 // block on the channel to receive an incoming mcast flow/group
3022 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003023 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
3024 if mcastFlowOrGroupCb.flow != nil {
3025 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3026 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
3027 log.Fields{"device-id": dh.device.Id,
3028 "flowToAdd": mcastFlowOrGroupCb.flow})
3029 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
3030 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
3031 // Pass the return value over the return channel
3032 *mcastFlowOrGroupCb.errChan <- err
3033 } else { // flow remove
3034 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
3035 log.Fields{"device-id": dh.device.Id,
3036 "flowToRemove": mcastFlowOrGroupCb.flow})
3037 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
3038 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
3039 // Pass the return value over the return channel
3040 *mcastFlowOrGroupCb.errChan <- err
3041 }
3042 } else { // mcast group
3043 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
3044 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
3045 log.Fields{"device-id": dh.device.Id,
3046 "groupToAdd": mcastFlowOrGroupCb.group})
3047 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3048 // Pass the return value over the return channel
3049 *mcastFlowOrGroupCb.errChan <- err
3050 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
3051 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
3052 log.Fields{"device-id": dh.device.Id,
3053 "groupToModify": mcastFlowOrGroupCb.group})
3054 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3055 // Pass the return value over the return channel
3056 *mcastFlowOrGroupCb.errChan <- err
3057 } else { // group remove
3058 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
3059 log.Fields{"device-id": dh.device.Id,
3060 "groupToRemove": mcastFlowOrGroupCb.group})
3061 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
3062 // Pass the return value over the return channel
3063 *mcastFlowOrGroupCb.errChan <- err
3064 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08003065 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003066 case <-stopHandler:
3067 dh.mcastHandlerRoutineActive[routineIndex] = false
3068 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08003069 }
3070 }
3071}
kesavand62126212021-01-12 04:56:06 -05003072
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003073// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003074func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003075 for i, v := range dh.stopMcastHandlerRoutine {
3076 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003077 select {
3078 case v <- true:
3079 case <-time.After(time.Second * 5):
3080 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
3081 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003082 }
3083 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003084 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07003085 logger.Debug(ctx, "stopped all mcast handler routines")
3086}
3087
kesavand62126212021-01-12 04:56:06 -05003088func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
3089
3090 singleValResp := extension.SingleGetValueResponse{
3091 Response: &extension.GetValueResponse{
3092 Response: &extension.GetValueResponse_PortCoutners{
3093 PortCoutners: &extension.GetOltPortCountersResponse{},
3094 },
3095 },
3096 }
3097
3098 errResp := func(status extension.GetValueResponse_Status,
3099 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3100 return &extension.SingleGetValueResponse{
3101 Response: &extension.GetValueResponse{
3102 Status: status,
3103 ErrReason: reason,
3104 },
3105 }
3106 }
3107
3108 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
3109 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
3110 //send error response
3111 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
3112 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
3113 }
3114 statIndChn := make(chan bool, 1)
3115 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
3116 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
3117 //request openOlt agent to send the the port statistics indication
3118
3119 go func() {
3120 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
3121 if err != nil {
3122 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
3123 }
3124 }()
3125 select {
3126 case <-statIndChn:
3127 //indication received for ports stats
3128 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
3129 case <-time.After(oltPortInfoTimeout * time.Second):
3130 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
3131 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3132 case <-ctx.Done():
3133 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
3134 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3135 }
3136 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
3137 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003138 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05003139 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
3140 cmnni := dh.portStats.collectNNIMetrics(intfID)
3141 if cmnni == nil {
3142 //TODO define the error reason
3143 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3144 }
3145 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
3146 return &singleValResp
3147
3148 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
3149 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003150 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05003151 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
3152 cmpon := dh.portStats.collectPONMetrics(intfID)
3153 if cmpon == nil {
3154 //TODO define the error reason
3155 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3156 }
3157 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
3158 return &singleValResp
3159 }
3160 }
3161 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3162}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05303163
3164func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
3165
3166 singleValResp := extension.SingleGetValueResponse{
3167 Response: &extension.GetValueResponse{
3168 Response: &extension.GetValueResponse_OnuPonCounters{
3169 OnuPonCounters: &extension.GetOnuCountersResponse{},
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 intfID := onuPonInfo.IntfId
3184 onuID := onuPonInfo.OnuId
3185 onuKey := dh.formOnuKey(intfID, onuID)
3186
3187 if _, ok := dh.onus.Load(onuKey); !ok {
3188 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3189 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3190 }
3191 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
3192 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
3193 if cmnni == nil {
3194 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3195 }
3196 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
3197 return &singleValResp
3198
3199}
Gamze Abaka85e9a142021-05-26 13:41:39 +00003200
3201func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
3202
3203 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3204 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3205 if err != nil {
3206 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3207 return generateSingleGetValueErrorResponse(err)
3208 }
3209 return &extension.SingleGetValueResponse{
3210 Response: &extension.GetValueResponse{
3211 Status: extension.GetValueResponse_OK,
3212 Response: &extension.GetValueResponse_RxPower{
3213 RxPower: &extension.GetRxPowerResponse{
3214 IntfId: rxPowerRequest.IntfId,
3215 OnuId: rxPowerRequest.OnuId,
3216 Status: rxPower.Status,
3217 FailReason: rxPower.FailReason.String(),
3218 RxPower: rxPower.RxPowerMeanDbm,
3219 },
3220 },
3221 },
3222 }
3223}
3224
3225func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3226 errResp := func(status extension.GetValueResponse_Status,
3227 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3228 return &extension.SingleGetValueResponse{
3229 Response: &extension.GetValueResponse{
3230 Status: status,
3231 ErrReason: reason,
3232 },
3233 }
3234 }
3235
3236 if err != nil {
3237 if e, ok := status.FromError(err); ok {
3238 switch e.Code() {
3239 case codes.Internal:
3240 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3241 case codes.DeadlineExceeded:
3242 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3243 case codes.Unimplemented:
3244 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3245 case codes.NotFound:
3246 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3247 }
3248 }
3249 }
3250
3251 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3252}
khenaidoo106c61a2021-08-11 18:05:46 -04003253
3254/*
3255Helper functions to communicate with Core
3256*/
3257
3258func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3259 cClient, err := dh.coreClient.GetCoreServiceClient()
3260 if err != nil || cClient == nil {
3261 return nil, err
3262 }
3263 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3264 defer cancel()
3265 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3266}
3267
khenaidoodc2116e2021-10-19 17:33:19 -04003268func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003269 cClient, err := dh.coreClient.GetCoreServiceClient()
3270 if err != nil || cClient == nil {
3271 return nil, err
3272 }
3273 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3274 defer cancel()
3275 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3276}
3277
khenaidoodc2116e2021-10-19 17:33:19 -04003278func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003279 cClient, err := dh.coreClient.GetCoreServiceClient()
3280 if err != nil || cClient == nil {
3281 return err
3282 }
3283 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3284 defer cancel()
3285 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3286 return err
3287}
3288
3289func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3290 cClient, err := dh.coreClient.GetCoreServiceClient()
3291 if err != nil || cClient == nil {
3292 return nil, err
3293 }
3294 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3295 defer cancel()
3296 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3297}
3298
3299func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3300 cClient, err := dh.coreClient.GetCoreServiceClient()
3301 if err != nil || cClient == nil {
3302 return nil, err
3303 }
3304 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3305 defer cancel()
3306 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3307}
3308
3309func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3310 cClient, err := dh.coreClient.GetCoreServiceClient()
3311 if err != nil || cClient == nil {
3312 return err
3313 }
3314 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3315 defer cancel()
3316 _, err = cClient.DeviceUpdate(subCtx, device)
3317 return err
3318}
3319
khenaidoodc2116e2021-10-19 17:33:19 -04003320func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003321 cClient, err := dh.coreClient.GetCoreServiceClient()
3322 if err != nil || cClient == nil {
3323 return nil, err
3324 }
3325 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3326 defer cancel()
3327 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3328}
3329
khenaidoodc2116e2021-10-19 17:33:19 -04003330func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003331 cClient, err := dh.coreClient.GetCoreServiceClient()
3332 if err != nil || cClient == nil {
3333 return err
3334 }
3335 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3336 defer cancel()
3337 _, err = cClient.SendPacketIn(subCtx, pkt)
3338 return err
3339}
3340
3341func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3342 cClient, err := dh.coreClient.GetCoreServiceClient()
3343 if err != nil || cClient == nil {
3344 return err
3345 }
3346 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3347 defer cancel()
3348 _, err = cClient.PortCreated(subCtx, port)
3349 return err
3350}
3351
khenaidoodc2116e2021-10-19 17:33:19 -04003352func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003353 cClient, err := dh.coreClient.GetCoreServiceClient()
3354 if err != nil || cClient == nil {
3355 return err
3356 }
3357 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3358 defer cancel()
3359 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3360 return err
3361}
3362
khenaidoodc2116e2021-10-19 17:33:19 -04003363func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003364 cClient, err := dh.coreClient.GetCoreServiceClient()
3365 if err != nil || cClient == nil {
3366 return err
3367 }
3368 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3369 defer cancel()
3370 _, err = cClient.PortStateUpdate(subCtx, portState)
3371 return err
3372}
3373
khenaidoodc2116e2021-10-19 17:33:19 -04003374func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003375 cClient, err := dh.coreClient.GetCoreServiceClient()
3376 if err != nil || cClient == nil {
3377 return nil, err
3378 }
3379 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3380 defer cancel()
3381 return cClient.GetDevicePort(subCtx, portFilter)
3382}
3383
3384/*
3385Helper functions to communicate with child adapter
3386*/
3387
khenaidoodc2116e2021-10-19 17:33:19 -04003388func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003389 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3390 if err != nil || aClient == nil {
3391 return err
3392 }
3393 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3394 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3395 defer cancel()
3396 _, err = aClient.OmciIndication(subCtx, response)
3397 return err
3398}
3399
khenaidoodc2116e2021-10-19 17:33:19 -04003400func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003401 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3402 if err != nil || aClient == nil {
3403 return err
3404 }
3405 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3406 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3407 defer cancel()
3408 _, err = aClient.OnuIndication(subCtx, onuInd)
3409 return err
3410}
3411
khenaidoodc2116e2021-10-19 17:33:19 -04003412func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003413 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3414 if err != nil || aClient == nil {
3415 return err
3416 }
3417 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3418 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3419 defer cancel()
3420 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3421 return err
3422}
3423
khenaidoodc2116e2021-10-19 17:33:19 -04003424func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003425 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3426 if err != nil || aClient == nil {
3427 return err
3428 }
3429 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3430 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3431 defer cancel()
3432 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3433 return err
3434}
3435
khenaidoodc2116e2021-10-19 17:33:19 -04003436func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003437 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3438 if err != nil || aClient == nil {
3439 return err
3440 }
3441 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3442 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3443 defer cancel()
3444 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3445 return err
3446}
3447
3448/*
3449Helper functions for remote communication
3450*/
3451
3452// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3453// supports is deleted
3454func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3455 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3456
3457 dh.lockChildAdapterClients.Lock()
3458 defer dh.lockChildAdapterClients.Unlock()
3459 if _, ok := dh.childAdapterClients[endpoint]; ok {
3460 // Already set
3461 return nil
3462 }
3463
3464 // Setup child's adapter grpc connection
3465 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003466 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3467 dh.cfg.AdapterEndpoint,
3468 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05003469 "onu_inter_adapter_service.OnuInterAdapterService",
3470 dh.onuInterAdapterRestarted,
3471 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003472 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3473 return err
3474 }
khenaidooefff76e2021-12-15 16:51:30 -05003475 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003476
3477 // Wait until we have a connection to the child adapter.
3478 // Unlimited retries or until context expires
3479 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3480 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3481 for {
3482 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3483 if err == nil && client != nil {
3484 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3485 break
3486 }
3487 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3488 // Backoff
3489 if err = backoff.Backoff(subCtx); err != nil {
3490 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3491 break
3492 }
3493 }
3494 return nil
3495}
3496
khenaidoodc2116e2021-10-19 17:33:19 -04003497func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003498
3499 // First check from cache
3500 dh.lockChildAdapterClients.RLock()
3501 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3502 dh.lockChildAdapterClients.RUnlock()
3503 return cgClient.GetOnuInterAdapterServiceClient()
3504 }
3505 dh.lockChildAdapterClients.RUnlock()
3506
3507 // Set the child connection - can occur on restarts
3508 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3509 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3510 cancel()
3511 if err != nil {
3512 return nil, err
3513 }
3514
3515 // Get the child client now
3516 dh.lockChildAdapterClients.RLock()
3517 defer dh.lockChildAdapterClients.RUnlock()
3518 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3519 return cgClient.GetOnuInterAdapterServiceClient()
3520 }
3521 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3522}
3523
3524func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3525 dh.lockChildAdapterClients.Lock()
3526 defer dh.lockChildAdapterClients.Unlock()
3527 for key, client := range dh.childAdapterClients {
3528 client.Stop(ctx)
3529 delete(dh.childAdapterClients, key)
3530 }
3531}
3532
khenaidooefff76e2021-12-15 16:51:30 -05003533// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
3534func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
3535 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003536 return nil
3537}
3538
khenaidooefff76e2021-12-15 16:51:30 -05003539// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
3540func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
3541 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003542 return nil
3543 }
khenaidooefff76e2021-12-15 16:51:30 -05003544 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04003545}
Girish Gowdra950326e2021-11-05 12:43:24 -07003546
3547func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3548 dh.lockDevice.Lock()
3549 defer dh.lockDevice.Unlock()
3550 dh.isDeviceDeletionInProgress = flag
3551}
3552
3553func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3554 dh.lockDevice.RLock()
3555 defer dh.lockDevice.RUnlock()
3556 return dh.isDeviceDeletionInProgress
3557}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003558
3559// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3560// Returns false if waiting timed out.
3561func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3562 c := make(chan struct{})
3563 go func() {
3564 defer close(c)
3565 wg.Wait()
3566 }()
3567 select {
3568 case <-c:
3569 return true // completed normally
3570 case <-time.After(timeout):
3571 return false // timed out
3572 }
3573}
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05303574
3575func (dh *DeviceHandler) updateHeartbeatSignature(ctx context.Context, signature uint32) {
3576 val, err := json.Marshal(signature)
3577 if err != nil {
3578 logger.Error(ctx, "failed-to-marshal")
3579 return
3580 }
3581 if err = dh.kvStore.Put(ctx, heartbeatPath, val); err != nil {
3582 logger.Error(ctx, "failed-to-store-hearbeat-signature")
3583 }
3584}
3585
3586func (dh *DeviceHandler) getHeartbeatSignature(ctx context.Context) uint32 {
3587 var signature uint32
3588
3589 Value, er := dh.kvStore.Get(ctx, heartbeatPath)
3590 if er == nil {
3591 if Value != nil {
3592 Val, er := kvstore.ToByte(Value.Value)
3593 if er != nil {
3594 logger.Errorw(ctx, "Failed to convert into byte array", log.Fields{"err": er})
3595 return signature
3596 }
3597 if er = json.Unmarshal(Val, &signature); er != nil {
3598 logger.Error(ctx, "Failed to unmarshal signature", log.Fields{"err": er})
3599 return signature
3600 }
3601 }
3602 }
3603 return signature
3604}