blob: 2d3c7c5c5dbb46e8017f9e013ce352e572587fd7 [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"
Girish Gowdra491a9c62021-01-06 16:43:07 -080024 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070025 "fmt"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040026 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070027 "strconv"
28 "strings"
29 "sync"
30 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053031
Elia Battiston599d25f2022-02-16 14:49:08 +010032 "github.com/opencord/voltha-lib-go/v7/pkg/db"
33 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
34
khenaidoo106c61a2021-08-11 18:05:46 -040035 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040036
Matteo Scandolo945e4012019-12-12 14:16:11 -080037 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070038 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000039 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
40 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040041 "github.com/opencord/voltha-lib-go/v7/pkg/config"
42 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
43 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
44 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070045 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040046 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080047
khenaidoo106c61a2021-08-11 18:05:46 -040048 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053049 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080050 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040051 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040052 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040053 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040054 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
55 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040056 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
57 oop "github.com/opencord/voltha-protos/v5/go/openolt"
58 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070059 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040060 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040061 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053062)
63
salmansiddiqui7ac62132019-08-22 03:58:50 +000064// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040065const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080066 InvalidPort = 0xffffffff
67 MaxNumOfGroupHandlerChannels = 256
68
69 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
70 McastFlowOrGroupModify = "McastFlowOrGroupModify"
71 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050072 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010073
74 defaultPortSpeedMbps = 1000
Manikkaraj kb1d51442019-07-23 10:41:02 -040075)
76
Phaneendra Manda4c62c802019-03-06 21:37:49 +053077//DeviceHandler will interact with the OLT device.
78type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040079 cm *config.ConfigManager
80 device *voltha.Device
81 cfg *conf.AdapterFlags
82 coreClient *vgrpc.Client
83 childAdapterClients map[string]*vgrpc.Client
84 lockChildAdapterClients sync.RWMutex
85 EventProxy eventif.EventProxy
86 openOLT *OpenOLT
khenaidooefff76e2021-12-15 16:51:30 -050087 exitChannel chan struct{}
khenaidoo106c61a2021-08-11 18:05:46 -040088 lockDevice sync.RWMutex
89 Client oop.OpenoltClient
90 transitionMap *TransitionMap
91 clientCon *grpc.ClientConn
92 flowMgr []*OpenOltFlowMgr
93 groupMgr *OpenOltGroupMgr
94 eventMgr *OpenOltEventMgr
95 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070096
97 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053098
Girish Gowdra3ab6d212020-03-24 17:33:15 -070099 discOnus sync.Map
100 onus sync.Map
101 portStats *OpenOltStatisticsMgr
102 metrics *pmmetrics.PmMetrics
103 stopCollector chan bool
104 stopHeartbeatCheck chan bool
105 activePorts sync.Map
106 stopIndications chan bool
107 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700108
Mahir Gunyelb0046752021-02-26 13:51:05 -0800109 totalPonPorts uint32
110 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
111 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800112
113 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
114 // 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 -0700115 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
116 stopMcastHandlerRoutine []chan bool
117 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000118
119 adapterPreviouslyConnected bool
120 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700121
122 isDeviceDeletionInProgress bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700123}
124
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700125//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700126type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400127 deviceID string
128 deviceType string
129 serialNumber string
130 onuID uint32
131 intfID uint32
132 proxyDeviceID string
133 losRaised bool
134 rdiRaised bool
135 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700136}
137
Mahir Gunyelb0046752021-02-26 13:51:05 -0800138type onuIndicationMsg struct {
139 ctx context.Context
140 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800141}
142
143type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800144 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800145 stopChannel chan struct{}
146}
147
Girish Gowdra491a9c62021-01-06 16:43:07 -0800148//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
149//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
150//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
151//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
152type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400153 ctx context.Context // Flow/group handler context
154 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
155 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
156 group *of.OfpGroupEntry // Group message (can be nil or valid group)
157 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800158}
159
Naga Manjunath7615e552019-10-11 22:35:47 +0530160var pmNames = []string{
161 "rx_bytes",
162 "rx_packets",
163 "rx_mcast_packets",
164 "rx_bcast_packets",
165 "tx_bytes",
166 "tx_packets",
167 "tx_mcast_packets",
168 "tx_bcast_packets",
169}
170
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700171//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400172func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700173 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700174 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700175 device.deviceType = deviceTp
176 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700177 device.onuID = onuID
178 device.intfID = intfID
179 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530180 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400181 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700182 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530183}
184
185//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400186func 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 -0700187 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800188 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400189 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400190 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700191 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700192 dh.device = cloned
193 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500194 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700195 dh.lockDevice = sync.RWMutex{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800196 dh.stopCollector = make(chan bool, 2) // TODO: Why buffered?
197 dh.stopHeartbeatCheck = make(chan bool, 2) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530198 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 -0500199 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800200 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800201 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400202 dh.childAdapterClients = make(map[string]*vgrpc.Client)
203 dh.cfg = cfg
Girish Gowdra491a9c62021-01-06 16:43:07 -0800204 // Create a slice of buffered channels for handling concurrent mcast flow/group.
205 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700206 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
207 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800208 for i := range dh.incomingMcastFlowOrGroup {
209 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800210 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800211 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
212 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
213 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
214 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700215 dh.mcastHandlerRoutineActive[i] = true
216 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800217 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700218 //TODO initialize the support classes.
219 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530220}
221
222// start save the device to the data model
223func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700224 dh.lockDevice.Lock()
225 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000226 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700227 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000228 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530229}
230
khenaidooefff76e2021-12-15 16:51:30 -0500231// Stop stops the device handler
232func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700233 dh.lockDevice.Lock()
234 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000235 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500236 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400237
khenaidooefff76e2021-12-15 16:51:30 -0500238 // Delete (which will stop also) all grpc connections to the child adapters
239 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000240 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530241}
242
ssiddiqui04386ee2021-08-23 21:58:25 +0530243func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
244 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
245 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
246 if pooledIntfID == intfID {
247 return resourceRanges.GetTechnology()
248 }
249 }
250 }
251 return ""
252}
253
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400254func macifyIP(ip net.IP) string {
255 if len(ip) > 0 {
256 oct1 := strconv.FormatInt(int64(ip[12]), 16)
257 oct2 := strconv.FormatInt(int64(ip[13]), 16)
258 oct3 := strconv.FormatInt(int64(ip[14]), 16)
259 oct4 := strconv.FormatInt(int64(ip[15]), 16)
260 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
261 }
262 return ""
263}
264
Neha Sharma96b7bf22020-06-15 10:37:32 +0000265func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400266 var genmac string
267 var addr net.IP
268 var ips []string
269 var err error
270
Neha Sharma96b7bf22020-06-15 10:37:32 +0000271 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400272
273 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000274 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400275
276 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000277 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400278 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000279 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400280 }
281 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000282 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530283 log.Fields{"host": ips[0],
284 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400285 return genmac, nil
286 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000287 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400288 }
289
290 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000291 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530292 log.Fields{"host": host,
293 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400294 return genmac, nil
295}
296
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530297func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700298 slist := strings.Split(mac, ":")
299 result := make([]uint32, len(slist))
300 var err error
301 var tmp int64
302 for index, val := range slist {
303 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
304 return []uint32{1, 2, 3, 4, 5, 6}
305 }
306 result[index] = uint32(tmp)
307 }
308 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530309}
310
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700311//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 -0800312func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530313
David K. Bainbridge794735f2020-02-11 21:01:37 -0800314 switch portType {
315 case voltha.Port_ETHERNET_NNI:
316 return fmt.Sprintf("nni-%d", portNum), nil
317 case voltha.Port_PON_OLT:
318 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700319 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800320
Girish Kumarf26e4882020-03-05 06:49:10 +0000321 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530322}
323
Elia Battiston596406d2022-02-02 12:19:00 +0100324func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
325 if speedMbps == 0 {
326 //In case it was not set in the indication
327 //and no other value was provided
328 speedMbps = defaultPortSpeedMbps
329 }
330
331 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
332 switch speedMbps {
333 case 1000000:
334 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
335 case 100000:
336 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
337 case 40000:
338 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
339 case 10000:
340 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
341 case 1000:
342 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
343 case 100:
344 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
345 case 10:
346 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
347 }
348
349 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
350
351 port := &of.OfpPort{
352 HwAddr: macAddressToUint32Array(macAddress),
353 Config: 0,
354 State: uint32(of.OfpPortState_OFPPS_LIVE),
355 Curr: capacity,
356 Advertised: capacity,
357 Peer: capacity,
358 CurrSpeed: speedMbps * 1000, //kbps
359 MaxSpeed: speedMbps * 1000, //kbps
360 }
361
362 return port
363}
364
365func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000366 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700367 if state == "up" {
368 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500369 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500370 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700371 } else {
372 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500373 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700374 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700375 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400376 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800377 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000378 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400379 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500380
khenaidoo106c61a2021-08-11 18:05:46 -0400381 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400382 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400383 DeviceId: dh.device.Id,
384 Port: portNum,
385 })
386 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000387 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400388 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400389 DeviceId: dh.device.Id,
390 PortType: portType,
391 PortNo: portNum,
392 OperStatus: operStatus})
393 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400394 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
395 "device-id": dh.device.Id,
396 "port-type": portType,
397 "port-number": portNum,
398 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500399 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400400 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500401 }
khenaidoo106c61a2021-08-11 18:05:46 -0400402
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400403 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400404 port = &voltha.Port{
405 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700406 PortNo: portNum,
407 Label: label,
408 Type: portType,
409 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100410 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700411 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000412 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700413 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400414 err = dh.createPortInCore(ctx, port)
415 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000416 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800417 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000418 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400419 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000420 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530421 return nil
422}
423
Kent Hagermane6ff1012020-07-14 15:07:53 -0400424func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400425 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530426 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400427 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
428 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530429 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800430 dh.lockDevice.Lock()
431 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530432 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530433}
434
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700435// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530436// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800437func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000438 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700439 defer func() {
440 dh.lockDevice.Lock()
441 dh.isReadIndicationRoutineActive = false
442 dh.lockDevice.Unlock()
443 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700444 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700445 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700446 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700447 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400448
David Bainbridgef5879ca2019-12-13 21:17:54 +0000449 // Create an exponential backoff around re-enabling indications. The
450 // maximum elapsed time for the back off is set to 0 so that we will
451 // continue to retry. The max interval defaults to 1m, but is set
452 // here for code clarity
453 indicationBackoff := backoff.NewExponentialBackOff()
454 indicationBackoff.MaxElapsedTime = 0
455 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700456
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700457 dh.lockDevice.Lock()
458 dh.isReadIndicationRoutineActive = true
459 dh.lockDevice.Unlock()
460
Girish Gowdra3f974912020-03-23 20:35:18 -0700461Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700462 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400463 select {
464 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000465 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700466 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400467 default:
468 indication, err := indications.Recv()
Elia Battiston599d25f2022-02-16 14:49:08 +0100469
470 select {
471 case <-indications.Context().Done():
472 if err != nil {
473 logger.Warnw(ctx, "error-during-enable-indications",
474 log.Fields{"err": err,
475 "device-id": dh.device.Id})
476 }
477
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400478 // Use an exponential back off to prevent getting into a tight loop
479 duration := indicationBackoff.NextBackOff()
Elia Battiston599d25f2022-02-16 14:49:08 +0100480 logger.Infow(ctx, "backing-off-enable-indication", log.Fields{
481 "device-id": dh.device.Id,
482 "duration": duration,
483 })
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400484 if duration == backoff.Stop {
485 // If we reach a maximum then warn and reset the backoff
486 // timer and keep attempting.
Elia Battiston599d25f2022-02-16 14:49:08 +0100487 logger.Warnw(ctx, "maximum-indication-backoff-reached-resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530488 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530489 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400490 indicationBackoff.Reset()
491 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700492
493 // On failure process a backoff timer while watching for stopIndications
494 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700495 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700496 select {
497 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000498 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700499 if !backoffTimer.Stop() {
500 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700501 }
502 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700503 case <-backoffTimer.C:
504 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700505 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700506 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
507 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400508 }
509 continue
Elia Battiston599d25f2022-02-16 14:49:08 +0100510 default:
511 if err != nil {
512 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530513 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530514 "device-id": dh.device.Id})
Elia Battiston599d25f2022-02-16 14:49:08 +0100515 // Close the stream, and re-initialize it
516 if err = indications.CloseSend(); err != nil {
517 // Ok to ignore here, because we landed here due to a problem on the stream
518 // In all probability, the closeSend call may fail
519 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
520 log.Fields{"err": err,
521 "device-id": dh.device.Id})
522 }
523 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
524 return err
525 }
526 // once we re-initialized the indication stream, continue to read indications
527 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700528 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100529 // Reset backoff if we have a successful receive
530 indicationBackoff.Reset()
531 // When OLT is admin down, ignore all indications.
532 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
533 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
534 log.Fields{"indication": indication,
535 "device-id": dh.device.Id})
536 continue
Girish Gowdra3f974912020-03-23 20:35:18 -0700537 }
Elia Battiston599d25f2022-02-16 14:49:08 +0100538 dh.handleIndication(ctx, indication)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530539 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700540 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700542 // Close the send stream
543 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700544
Girish Gowdra3f974912020-03-23 20:35:18 -0700545 return nil
546}
547
548func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700549 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700550 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
551 if err != nil {
552 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
553 }
554 if indications == nil {
555 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
556 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700557 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700558 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400559}
560
561// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
562func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
563 switch indication.Data.(type) {
564 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
565 return true
566
567 default:
568 return false
569 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700570}
571
David K. Bainbridge794735f2020-02-11 21:01:37 -0800572func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700573 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000574 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530575 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530577 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700578 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000579 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000580 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530581 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000582 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800583 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000584 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800585 }
586 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700587}
588
David K. Bainbridge794735f2020-02-11 21:01:37 -0800589// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530590func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700591 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700592 switch indication.Data.(type) {
593 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000594 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
595 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700596 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 -0800597 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400598 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800599 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700600 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000601 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
602 defer span.Finish()
603
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700604 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800605 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100606 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400607 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800608 }
609 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000610 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700611 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000612 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
613 defer span.Finish()
614
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700615 intfOperInd := indication.GetIntfOperInd()
616 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800617 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100618 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400619 _ = 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 -0800620 }
621 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 } else if intfOperInd.GetType() == "pon" {
623 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
624 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800625 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100626 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400627 _ = 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 -0800628 }
629 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000630 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700631 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000632 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530633 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530634 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700635 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000636 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
637 defer span.Finish()
638
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700639 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000640 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800641 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800642 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700643 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000644 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
645 defer span.Finish()
646
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700647 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000648 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800649 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800650 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000652 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
653 defer span.Finish()
654
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000656 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 -0800657 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000658 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400659 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800660 }
661 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000663 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
664 defer span.Finish()
665
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700666 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000667 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700668 "intf-type": pktInd.IntfId,
669 "intf-id": pktInd.IntfId,
670 "gem-port-id": pktInd.GemportId,
671 "port-no": pktInd.PortNo,
672 "device-id": dh.device.Id,
673 })
674
675 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000676 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700677 "intf-type": pktInd.IntfId,
678 "intf-id": pktInd.IntfId,
679 "gem-port-id": pktInd.GemportId,
680 "port-no": pktInd.PortNo,
681 "packet": hex.EncodeToString(pktInd.Pkt),
682 "device-id": dh.device.Id,
683 })
684 }
685
David K. Bainbridge794735f2020-02-11 21:01:37 -0800686 go func() {
687 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400688 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800689 }
690 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000692 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
693 defer span.Finish()
694
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700695 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700696 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000698 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
699 defer span.Finish()
700
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700701 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700703 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000704 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
705 defer span.Finish()
706
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700707 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000708 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
709 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700710 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530711}
712
713// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530714func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530715 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000716 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530717
Girish Gowdra618fa572021-09-01 17:19:29 -0700718 // instantiate the mcast handler routines.
719 for i := range dh.incomingMcastFlowOrGroup {
720 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
721 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
722 if !dh.mcastHandlerRoutineActive[i] {
723 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
724 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
725 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
726 // for incoming mcast flow/group to be processed serially.
727 dh.mcastHandlerRoutineActive[i] = true
728 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
729 }
730 }
731
Girish Gowdru0c588b22019-04-23 23:24:56 -0400732 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400733 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400734 DeviceId: dh.device.Id,
735 OperStatus: voltha.OperStatus_ACTIVE,
736 ConnStatus: voltha.ConnectStatus_REACHABLE,
737 }); err != nil {
738 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400739 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000740
741 //Clear olt communication failure event
742 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
743 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700744 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000745 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
746
Gamze Abakac2c32a62021-03-11 11:44:18 +0000747 //check adapter and agent reconcile status
748 //reboot olt if needed (olt disconnection case)
749 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
750 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
751 log.Fields{
752 "device-id": dh.device.Id,
753 "adapter-status": dh.adapterPreviouslyConnected,
754 "agent-status": dh.agentPreviouslyConnected,
755 })
756 _ = dh.RebootDevice(ctx, dh.device)
757 }
758
Girish Gowdru0c588b22019-04-23 23:24:56 -0400759 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530760}
761
762// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530763func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000764 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400765
khenaidoo106c61a2021-08-11 18:05:46 -0400766 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400767 if err != nil || device == nil {
768 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000769 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400770 }
771
772 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400773
774 //Update the device oper state and connection status
775 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800776 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400777 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800778 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400779
khenaidoodc2116e2021-10-19 17:33:19 -0400780 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400781 DeviceId: cloned.Id,
782 OperStatus: cloned.OperStatus,
783 ConnStatus: cloned.ConnectStatus,
784 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000785 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400786 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400787
788 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400789 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400790 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000791 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400792 }
793 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400794 // Update onu state as down in onu adapter
795 onuInd := oop.OnuIndication{}
796 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400797
798 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
799 if err != nil {
800 return err
801 }
802 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400803 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400804 DeviceId: onuDevice.Id,
805 OnuIndication: &onuInd,
806 })
807 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800808 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400809 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400810 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800811 "onu-indicator": onuInd,
812 "device-type": onuDevice.Type,
813 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700814 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800815 } else {
816 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 -0700817 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400818 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800819 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700820 /* Discovered ONUs entries need to be cleared , since after OLT
821 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530822 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800823 dh.lockDevice.Unlock()
824
Neha Sharma96b7bf22020-06-15 10:37:32 +0000825 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700826 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530827}
828
829// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530830func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400831 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000832
833 // if the connection is already available, close the previous connection (olt reboot case)
834 if dh.clientCon != nil {
835 if err = dh.clientCon.Close(); err != nil {
836 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
837 } else {
838 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
839 }
840 }
841
842 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000843 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
844 grpc.WithInsecure(),
845 grpc.WithBlock(),
846 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000847 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000848 )),
849 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000850 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000851 )))
852
853 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530854 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530855 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000856 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400857 }
858 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530859}
860
861// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530862func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400863 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530864 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400865 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530866}
867
868// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530869func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530870 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000871 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400872
873 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400874 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530875 if err != nil || device == nil {
876 /*TODO: needs to handle error scenarios */
877 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
878 }
879 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000880 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400881
882 cloned := proto.Clone(device).(*voltha.Device)
883 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
884 cloned.OperStatus = voltha.OperStatus_UNKNOWN
885 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400886
khenaidoodc2116e2021-10-19 17:33:19 -0400887 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400888 DeviceId: cloned.Id,
889 OperStatus: cloned.OperStatus,
890 ConnStatus: cloned.ConnectStatus,
891 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530892 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 -0400893 }
894
Chaitrashree G S44124192019-08-07 20:21:36 -0400895 // 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 +0530896 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400897 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530898 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400899 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400900 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
901 // all the modules initialized and ready to handle incoming ONUs.
902
Thomas Lee S985938d2020-05-04 11:40:41 +0530903 err = dh.initializeDeviceHandlerModules(ctx)
904 if err != nil {
905 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 -0400906 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400907
908 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800909 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530910 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400911 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800912 }
913 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700914
915 go startHeartbeatCheck(ctx, dh)
916
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400917 return nil
918 }
919
khenaidoo106c61a2021-08-11 18:05:46 -0400920 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400921 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400922 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400923 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400924 }
khenaidoo106c61a2021-08-11 18:05:46 -0400925 dh.populateActivePorts(ctx, ports.Items)
926 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400927 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400928 }
929
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400930 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530931 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 -0400932 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530933
cuilin20187b2a8c32019-03-26 19:52:28 -0700934 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800935 go func() {
936 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400937 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800938 }
939 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000940 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000941
942 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000943 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000944 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700945
946 go startHeartbeatCheck(ctx, dh)
947
cuilin20187b2a8c32019-03-26 19:52:28 -0700948 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530949}
950
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400951func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700952 var err error
953 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400954
955 if err != nil {
956 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
957 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700958 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
959 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +0000960 // +1 is for NNI
961 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
962 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700963 var i uint32
yasin saplid0566272021-12-21 09:10:30 +0000964 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
965 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
966 // There is only one NNI manager since multiple NNI is not supported for now
967 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700968 // Instantiate resource manager
969 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 -0700970 return olterrors.ErrResourceManagerInstantiating
971 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400972 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700973 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
974 // the KV store to manage mcast group data. Provide the first instance (0th index)
975 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
976 return olterrors.ErrGroupManagerInstantiating
977 }
yasin saplid0566272021-12-21 09:10:30 +0000978 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700979 // Instantiate flow manager
980 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
981 return olterrors.ErrFlowManagerInstantiating
982 }
Girish Gowdra76a1b092021-07-28 10:07:04 -0700983 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700984 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400985 /* TODO: Instantiate Alarm , stats , BW managers */
986 /* Instantiating Event Manager to handle Alarms and KPIs */
987 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
988
989 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000990 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400991
992 return nil
993
994}
995
Neha Sharma96b7bf22020-06-15 10:37:32 +0000996func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400997 var err error
998 var deviceInfo *oop.DeviceInfo
999
Neha Sharma8f4e4322020-08-06 10:51:53 +00001000 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001001
1002 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001003 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001004 }
1005 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001006 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001007 }
1008
Neha Sharma96b7bf22020-06-15 10:37:32 +00001009 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001010 dh.device.Root = true
1011 dh.device.Vendor = deviceInfo.Vendor
1012 dh.device.Model = deviceInfo.Model
1013 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1014 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1015 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1016
1017 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001018 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001019 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001020 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001021 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001022 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001023 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001024 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001025 dh.device.MacAddress = genmac
1026 } else {
1027 dh.device.MacAddress = deviceInfo.DeviceId
1028 }
1029
1030 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001031 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001032 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001033 }
1034
1035 return deviceInfo, nil
1036}
1037
Neha Sharma96b7bf22020-06-15 10:37:32 +00001038func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001039 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301040 for {
1041 select {
1042 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001043 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301044 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001045 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001046
khenaidoo106c61a2021-08-11 18:05:46 -04001047 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001048 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001049 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001050 continue
1051 }
khenaidoo106c61a2021-08-11 18:05:46 -04001052 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301053 // NNI Stats
1054 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001055 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301056 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001057 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001058 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001059 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301060 }
1061 // PON Stats
1062 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001063 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301064 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1065 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001066 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001067 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301068 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001069 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001070
yasin sapli9e4c5092022-02-01 13:52:33 +00001071 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001072 if len(onuGemInfoLst) > 0 {
1073 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001074 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001075 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301076 }
1077 }
1078 }
1079}
1080
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001081//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301082func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001083 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301085 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301086
1087 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001088 cgClient, err := dh.coreClient.GetCoreServiceClient()
1089 if err != nil {
1090 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1091 return
1092 }
1093
1094 // Now, set the initial PM configuration for that device
1095 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001096 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301097 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301098}
1099
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001100//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001101func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1102 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001103 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301104 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001105 HwDesc: "open_pon",
1106 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001107 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001108 },
1109 SwitchFeatures: &of.OfpSwitchFeatures{
1110 NBuffers: 256,
1111 NTables: 2,
1112 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1113 of.OfpCapabilities_OFPC_TABLE_STATS |
1114 of.OfpCapabilities_OFPC_PORT_STATS |
1115 of.OfpCapabilities_OFPC_GROUP_STATS),
1116 },
1117 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301118}
1119
khenaidoo106c61a2021-08-11 18:05:46 -04001120// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001121func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001122 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001123 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001124 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001125 }
khenaidoo106c61a2021-08-11 18:05:46 -04001126 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001127}
1128
Neha Sharma96b7bf22020-06-15 10:37:32 +00001129func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001130 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 -07001131 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001132 var deviceID string
1133 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001134 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001135
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001136 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001137 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 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 -07001139 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1140 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001141
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001142 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301143
1144 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1145
Neha Sharma96b7bf22020-06-15 10:37:32 +00001146 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 -07001147 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001148
khenaidoodc2116e2021-10-19 17:33:19 -04001149 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001150 ParentId: dh.device.Id,
1151 OnuId: omciInd.OnuId,
1152 ParentPortNo: ponPort,
1153 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301155 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001156 "intf-id": omciInd.IntfId,
1157 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001158 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001159 deviceType = onuDevice.Type
1160 deviceID = onuDevice.Id
1161 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001162 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001163 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001164 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001165 } else {
1166 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001167 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 +05301168 deviceType = onuInCache.(*OnuDevice).deviceType
1169 deviceID = onuInCache.(*OnuDevice).deviceID
1170 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001171 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001172 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001173
khenaidoodc2116e2021-10-19 17:33:19 -04001174 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001175 ParentDeviceId: proxyDeviceID,
1176 ChildDeviceId: deviceID,
1177 Message: omciInd.Pkt,
1178 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301179 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001180 "source": dh.openOLT.config.AdapterEndpoint,
1181 "device-type": deviceType,
1182 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001184 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001185 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301187}
1188
khenaidoo106c61a2021-08-11 18:05:46 -04001189// //ProcessInterAdapterMessage sends the proxied messages to the target device
1190// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1191// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001192// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001193// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001194// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001195// return dh.handleInterAdapterOmciMsg(ctx, msg)
1196// }
1197// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1198// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001199
kesavandb9f54fd2021-11-25 20:08:04 +05301200// ProxyOmciRequests sends the proxied OMCI message to the target device
1201func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
1202 if omciMsgs.GetProxyAddress() == nil {
1203 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1204 if err != nil {
1205 return olterrors.NewErrNotFound("onu", log.Fields{
1206 "parent-device-id": dh.device.Id,
1207 "child-device-id": omciMsgs.ChildDeviceId}, err)
1208 }
1209 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1210 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1211 return olterrors.NewErrCommunication("send-failed", log.Fields{
1212 "parent-device-id": dh.device.Id,
1213 "child-device-id": omciMsgs.ChildDeviceId}, err)
1214 }
1215 } else {
1216 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1217 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1218 return olterrors.NewErrCommunication("send-failed", log.Fields{
1219 "parent-device-id": dh.device.Id,
1220 "child-device-id": omciMsgs.ChildDeviceId}, err)
1221 }
1222 }
1223 return nil
1224}
1225
1226func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1227 var intfID uint32
1228 var onuID uint32
1229 var connectStatus common.ConnectStatus_Types
1230 if onuDevice != nil {
1231 intfID = onuDevice.ProxyAddress.GetChannelId()
1232 onuID = onuDevice.ProxyAddress.GetOnuId()
1233 connectStatus = onuDevice.ConnectStatus
1234 } else {
1235 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1236 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1237 connectStatus = omciMsgs.GetConnectStatus()
1238 }
1239 if connectStatus != voltha.ConnectStatus_REACHABLE {
1240 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1241
1242 return olterrors.NewErrCommunication("unreachable", log.Fields{
1243 "intf-id": intfID,
1244 "onu-id": onuID}, nil)
1245 }
1246
1247 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1248 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1249
1250 onuSecOmciMsgList := omciMsgs.GetMessages()
1251
1252 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1253
1254 var omciMessage *oop.OmciMsg
1255 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1256 hex.Encode(hexPkt, onuSecOmciMsg)
1257 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1258
1259 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1260 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1261 //https://jira.opencord.org/browse/VOL-4604
1262 transid := extractOmciTransactionID(onuSecOmciMsg)
1263 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1264 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1265
1266 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1267 if err != nil {
1268 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1269 "intf-id": intfID,
1270 "onu-id": onuID,
1271 "message": omciMessage}, err)
1272 }
1273 }
1274 return nil
1275}
1276
khenaidoo106c61a2021-08-11 18:05:46 -04001277// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001278func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001279 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 -07001280
1281 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001282 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001283 if err != nil {
1284 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001285 "parent-device-id": dh.device.Id,
1286 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001287 }
khenaidoo106c61a2021-08-11 18:05:46 -04001288 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1289 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001290 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001291 "parent-device-id": dh.device.Id,
1292 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001293 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001294 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001295 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1296 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001297 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001298 "parent-device-id": dh.device.Id,
1299 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001300 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001301 }
1302 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301303}
1304
khenaidoodc2116e2021-10-19 17:33:19 -04001305func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001306 var intfID uint32
1307 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001308 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001309 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001310 intfID = onuDevice.ProxyAddress.GetChannelId()
1311 onuID = onuDevice.ProxyAddress.GetOnuId()
1312 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001313 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001314 intfID = omciMsg.GetProxyAddress().GetChannelId()
1315 onuID = omciMsg.GetProxyAddress().GetOnuId()
1316 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001317 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001318 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001319 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 -08001320
Thomas Lee S94109f12020-03-03 16:39:29 +05301321 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001322 "intf-id": intfID,
1323 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001324 }
1325
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001326 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1327 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301328 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001329 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001330 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1331 hex.Encode(hexPkt, omciMsg.Message)
1332 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1333
1334 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1335 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1336 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001337 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001338 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001339
Neha Sharma8f4e4322020-08-06 10:51:53 +00001340 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001341 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301342 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001343 "intf-id": intfID,
1344 "onu-id": onuID,
1345 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001346 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001347 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001348}
1349
David K. Bainbridge794735f2020-02-11 21:01:37 -08001350func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301351 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 +00001352 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001353 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001354 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001355 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301356 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301357 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001358 st, _ := status.FromError(err)
1359 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001360 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1361
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001362 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301363 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001364 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001365 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001366 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001367 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001368 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001369}
1370
Mahir Gunyelb0046752021-02-26 13:51:05 -08001371func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001372 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001373 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001374
Mahir Gunyelb0046752021-02-26 13:51:05 -08001375 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001376 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301377
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301378 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001379 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001380 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301381
1382 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1383 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1384 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1385 OnuLosRaise event sent for it */
1386 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1387 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1388 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001389 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301390 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1391 "currentIntfId": onuDiscInd.GetIntfId()})
1392 // TODO:: Should we need to ignore raising OnuLosClear event
1393 // when onu connected to different PON?
1394 }
1395 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1396 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1397 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001398 go func() {
1399 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001400 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001401 }
1402 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301403 }
1404 return true
1405 })
1406
Neha Sharma96b7bf22020-06-15 10:37:32 +00001407 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001408 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001409 }
1410
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001411 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001412
1413 // check the ONU is already know to the OLT
1414 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001415 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001416 ParentId: dh.device.Id,
1417 SerialNumber: sn,
1418 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001419
1420 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001421 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 -08001422 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001423 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 -08001424 switch e.Code() {
1425 case codes.Internal:
1426 // this probably means NOT FOUND, so just create a new device
1427 onuDevice = nil
1428 case codes.DeadlineExceeded:
1429 // if the call times out, cleanup and exit
1430 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001431 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001432 }
1433 }
1434 }
1435
1436 if onuDevice == nil {
1437 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001438 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001439 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001440 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001441 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001442
Neha Sharma96b7bf22020-06-15 10:37:32 +00001443 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001444
1445 if err != nil {
1446 // if we can't create an ID in resource manager,
1447 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001448 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001449 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001450 "pon-intf-id": ponintfid,
1451 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001452 }
1453
khenaidoodc2116e2021-10-19 17:33:19 -04001454 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001455 ParentId: dh.device.Id,
1456 ParentPortNo: parentPortNo,
1457 ChannelId: channelID,
1458 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1459 SerialNumber: sn,
1460 OnuId: onuID,
1461 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001462 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001463 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 +05301464 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001465 "pon-intf-id": ponintfid,
1466 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001467 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001468 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 -07001469 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001470 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001471 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301472 log.Fields{"onuDevice": onuDevice,
1473 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001474 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301475 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001476 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001477
khenaidoo106c61a2021-08-11 18:05:46 -04001478 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1479 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1480 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1481 cancel()
1482 if err != nil {
1483 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1484 }
1485
Matteo Scandolo945e4012019-12-12 14:16:11 -08001486 // we can now use the existing ONU Id
1487 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001488 //Insert the ONU into cache to use in OnuIndication.
1489 //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 +00001490 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001491 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301492 "intfId": onuDiscInd.GetIntfId(),
1493 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001494 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001495
khenaidoo106c61a2021-08-11 18:05:46 -04001496 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301497 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001498 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301499 log.Fields{"onu": onuDev,
1500 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001501
khenaidoodc2116e2021-10-19 17:33:19 -04001502 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001503 DeviceId: onuDevice.Id,
1504 ParentDeviceId: dh.device.Id,
1505 OperStatus: common.OperStatus_DISCOVERED,
1506 ConnStatus: common.ConnectStatus_REACHABLE,
1507 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301508 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001509 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001510 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001511 }
khenaidoo106c61a2021-08-11 18:05:46 -04001512
Neha Sharma96b7bf22020-06-15 10:37:32 +00001513 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001514 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301515 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001516 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001517 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001518 }
1519 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001520}
1521
Mahir Gunyelb0046752021-02-26 13:51:05 -08001522func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001523
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001524 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001525 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001526 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001527 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001528 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301529 log.Fields{"onuId": onuInd.OnuId,
1530 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301531 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001532 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001533 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301534
David K. Bainbridge794735f2020-02-11 21:01:37 -08001535 errFields := log.Fields{"device-id": dh.device.Id}
1536
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301537 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1538
Mahir Gunyele77977b2019-06-27 05:36:22 -07001539 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1540 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001541 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001542 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001543 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001544 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1545 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001546 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001547 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001548 errFields["onu-id"] = onuInd.OnuId
1549 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001550 }
khenaidoodc2116e2021-10-19 17:33:19 -04001551 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001552 ParentId: dh.device.Id,
1553 SerialNumber: serialNumber,
1554 OnuId: onuInd.OnuId,
1555 ParentPortNo: ponPort,
1556 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001557 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001558
David K. Bainbridge794735f2020-02-11 21:01:37 -08001559 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001560 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001561 }
1562
David K. Bainbridge794735f2020-02-11 21:01:37 -08001563 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001564 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001565 "previousIntfId": onuDevice.ParentPortNo,
1566 "currentIntfId": ponPort})
1567 }
1568
1569 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301571 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1572 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301573 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001574 }
1575 if !foundInCache {
1576 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1577
khenaidoo106c61a2021-08-11 18:05:46 -04001578 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 -08001579
1580 }
kesavand7cf3a052020-08-28 12:49:18 +05301581 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001582 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001583 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301584 }
1585 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001586 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001587 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001588 }
1589 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001590}
1591
Neha Sharma96b7bf22020-06-15 10:37:32 +00001592func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001593 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 -07001594 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1595 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1596 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1597 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001598 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001599 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1600 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001601 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001602 onuInd.OperState = "down"
1603 }
1604 }
1605
David K. Bainbridge794735f2020-02-11 21:01:37 -08001606 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001607 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001608 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 -04001609
khenaidoodc2116e2021-10-19 17:33:19 -04001610 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001611 DeviceId: onuDevice.Id,
1612 OnuIndication: onuInd,
1613 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001614 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301615 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001616 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001617 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001618 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001619 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001620 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001621 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001622 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001623 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001624 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001625}
1626
cuilin20187b2a8c32019-03-26 19:52:28 -07001627func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1628 if serialNum != nil {
1629 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001630 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001631 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001632}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001633func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1634 decodedStr, err := hex.DecodeString(serialNum[4:])
1635 if err != nil {
1636 return nil, err
1637 }
1638 return &oop.SerialNumber{
1639 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001640 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001641 }, nil
1642}
cuilin20187b2a8c32019-03-26 19:52:28 -07001643
1644func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001645 if len(vendorSpecific) > 3 {
1646 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1647 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1648 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1649 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1650 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1651 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1652 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1653 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1654 return tmp
1655 }
1656 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001657}
1658
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001659//UpdateFlowsBulk upates the bulk flow
1660func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301661 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001662}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001663
1664//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001665func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1666 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301667 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001668 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301669 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001670
khenaidoodc2116e2021-10-19 17:33:19 -04001671 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001672 ParentId: dh.device.Id,
1673 OnuId: onuID,
1674 ParentPortNo: parentPort,
1675 })
1676
Girish Gowdru0c588b22019-04-23 23:24:56 -04001677 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001678 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001679 "intf-id": parentPort,
1680 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001681 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001682 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 -08001683 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301684}
1685
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001686// SendPacketInToCore sends packet-in to core
1687// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1688// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001689func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001690 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001691 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001692 "port": logicalPort,
1693 "packet": hex.EncodeToString(packetPayload),
1694 "device-id": dh.device.Id,
1695 })
1696 }
khenaidoo106c61a2021-08-11 18:05:46 -04001697
khenaidoodc2116e2021-10-19 17:33:19 -04001698 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001699 DeviceId: dh.device.Id,
1700 Port: logicalPort,
1701 Packet: packetPayload,
1702 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301703 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 "source": "adapter",
1705 "destination": "core",
1706 "device-id": dh.device.Id,
1707 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001708 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001709 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001710 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001711 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001712 "packet": hex.EncodeToString(packetPayload),
1713 "device-id": dh.device.Id,
1714 })
1715 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001716 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001717}
1718
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001719// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001720func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001721 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001722
1723 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1724 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001725 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001726 }
1727
Kent Hagermane6ff1012020-07-14 15:07:53 -04001728 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001729 metrics := dh.metrics.GetSubscriberMetrics()
1730 for _, m := range pmConfigs.Metrics {
1731 metrics[m.Name].Enabled = m.Enabled
1732
1733 }
1734 }
1735}
1736
khenaidoodc2116e2021-10-19 17:33:19 -04001737func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001738 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001739 var errorsList []error
1740
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001741 if dh.getDeviceDeletionInProgressFlag() {
1742 // The device itself is going to be reset as part of deletion. So nothing to be done.
1743 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1744 return nil
1745 }
1746
Girish Gowdru0c588b22019-04-23 23:24:56 -04001747 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001748 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001749 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001750
Neha Sharma96b7bf22020-06-15 10:37:32 +00001751 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301752 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001753 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301754 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001755 if flow_utils.HasGroup(flow) {
1756 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1757 } else {
yasin saplid0566272021-12-21 09:10:30 +00001758 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
Girish Gowdra491a9c62021-01-06 16:43:07 -08001759 }
Girish Gowdracefae192020-03-19 18:14:10 -07001760 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01001761 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
1762 //The flow we want to remove is not there, there is no need to throw an error
1763 logger.Warnw(ctx, "flow-to-remove-not-found",
1764 log.Fields{
1765 "ponIf": intfID,
1766 "flowToRemove": flow,
1767 "error": err,
1768 })
1769 } else {
1770 errorsList = append(errorsList, err)
1771 }
Girish Gowdracefae192020-03-19 18:14:10 -07001772 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001773 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301774
1775 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00001776 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001777 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301778 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001779 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301780 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001781 if flow_utils.HasGroup(flow) {
1782 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1783 } else {
yasin saplid0566272021-12-21 09:10:30 +00001784 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001785 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1786 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1787 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1788 } else {
yasin saplid0566272021-12-21 09:10:30 +00001789 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001790 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001791 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001792 if err != nil {
1793 errorsList = append(errorsList, err)
1794 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301795 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001796 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001797
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001798 return errorsList
1799}
1800
1801func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1802 var err error
1803 var errorsList []error
1804
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001805 if dh.getDeviceDeletionInProgressFlag() {
1806 // The device itself is going to be reset as part of deletion. So nothing to be done.
1807 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1808 return nil
1809 }
1810
Girish Gowdracefae192020-03-19 18:14:10 -07001811 // 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 +00001812 if groups != nil {
1813 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001814 // err = dh.groupMgr.AddGroup(ctx, group)
1815 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001816 if err != nil {
1817 errorsList = append(errorsList, err)
1818 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001819 }
1820 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001821 // err = dh.groupMgr.ModifyGroup(ctx, group)
1822 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001823 if err != nil {
1824 errorsList = append(errorsList, err)
1825 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001826 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001827 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001828 // err = dh.groupMgr.DeleteGroup(ctx, group)
1829 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001830 if err != nil {
1831 errorsList = append(errorsList, err)
1832 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001833 }
1834 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001835
1836 return errorsList
1837}
1838
1839//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001840func (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 -07001841
1842 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001843
1844 if dh.getDeviceDeletionInProgressFlag() {
1845 // The device itself is going to be reset as part of deletion. So nothing to be done.
1846 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1847 return nil
1848 }
1849
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001850 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1851 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1852 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001853 if len(errorsList) > 0 {
1854 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1855 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001856 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001857 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301858}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001859
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001860//DisableDevice disables the given device
1861//It marks the following for the given device:
1862//Device-Handler Admin-State : down
1863//Device Port-State: UNKNOWN
1864//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001865func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001866 /* On device disable ,admin state update has to be done prior sending request to agent since
1867 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001868 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001869 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001870 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001871 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001872 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001873 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001874 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001876 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001877 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301878
1879 dh.discOnus = sync.Map{}
1880 dh.onus = sync.Map{}
1881
Thomas Lee S85f37312020-04-03 17:06:12 +05301882 //stopping the stats collector
1883 dh.stopCollector <- true
1884
Neha Sharma96b7bf22020-06-15 10:37:32 +00001885 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001886 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301887 //Update device Admin state
1888 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001889
kdarapu1afeceb2020-02-12 01:38:09 -05001890 // 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 -04001891 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001892 DeviceId: cloned.Id,
1893 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
1894 OperStatus: voltha.OperStatus_UNKNOWN,
1895 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001896 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001897 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001898 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001899 return nil
1900}
1901
Neha Sharma96b7bf22020-06-15 10:37:32 +00001902func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001903 // Update onu state as unreachable in onu adapter
1904 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301905 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04001906
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001907 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001908 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001909 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001910 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 -04001911 }
1912 if onuDevices != nil {
1913 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04001914 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001915 DeviceId: onuDevice.Id,
1916 OnuIndication: &onuInd,
1917 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001918 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001919 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001920 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001921 }
1922
1923 }
1924 }
1925
1926}
1927
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001928//ReenableDevice re-enables the olt device after disable
1929//It marks the following for the given device:
1930//Device-Handler Admin-State : up
1931//Device Port-State: ACTIVE
1932//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001933func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001934 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301935 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001936 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301937 }
1938 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001939 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001940
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001941 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04001942 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001943 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001944 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001945 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
1946 } else {
1947 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1948 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
1949 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001950 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001951 if retError == nil {
1952 //Update the device oper status as ACTIVE
1953 device.OperStatus = voltha.OperStatus_ACTIVE
1954 } else {
1955 //Update the device oper status as FAILED
1956 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001957 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001958 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001959
khenaidoodc2116e2021-10-19 17:33:19 -04001960 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001961 DeviceId: device.Id,
1962 OperStatus: device.OperStatus,
1963 ConnStatus: device.ConnectStatus,
1964 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301965 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001966 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001967 "connect-status": device.ConnectStatus,
1968 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001969 }
kesavand39e0aa32020-01-28 20:58:50 -05001970
Neha Sharma96b7bf22020-06-15 10:37:32 +00001971 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001972
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001973 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001974}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001975
npujarec5762e2020-01-01 14:08:48 +05301976func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001977 var uniID uint32
1978 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301979 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001980 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001981 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001982 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001983 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001984 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001985 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001986 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00001987 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001988 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00001989 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001990 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001991 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001992 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00001993 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001994 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001995 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001996 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301997 }
yasin saplibddc2d72022-02-08 13:10:17 +00001998 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
1999 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002000 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302001 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002002 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00002003 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002004 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 +00002005 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002006 }
2007 return nil
2008}
2009
Devmalya Paul495b94a2019-08-27 19:42:00 -04002010// 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 +05302011func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002012 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002013 /* Clear the KV store data associated with the all the UNI ports
2014 This clears up flow data and also resource map data for various
2015 other pon resources like alloc_id and gemport_id
2016 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002017
2018 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002019 var wg sync.WaitGroup
2020 wg.Add(1) // for the mcast routine below to finish
2021 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2022 for _, flMgr := range dh.flowMgr {
2023 wg.Add(1) // for the flow handler routine below to finish
2024 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2025 }
2026 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2027 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2028 } else {
2029 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2030 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002031
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002032 dh.cleanupDeviceResources(ctx)
2033 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 -04002034 // Stop the Stats collector
2035 dh.stopCollector <- true
2036 // stop the heartbeat check routine
2037 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05302038 dh.lockDevice.RLock()
2039 // Stop the read indication only if it the routine is active
2040 if dh.isReadIndicationRoutineActive {
2041 dh.stopIndications <- true
2042 }
2043 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002044 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002045 //Reset the state
2046 if dh.Client != nil {
2047 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302048 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002049 }
2050 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002051 // There is no need to update the core about operation status and connection status of the OLT.
2052 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2053 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2054 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002055
khenaidoo7eb2d672021-10-22 19:08:50 -04002056 // Stop the adapter grpc clients for that parent device
2057 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002058 return nil
2059}
Kent Hagermane6ff1012020-07-14 15:07:53 -04002060func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002061
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002062 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302063 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002064 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002065 var err error
yasin sapli9e4c5092022-02-01 13:52:33 +00002066 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002067 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002068 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002069 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002070 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302071 }
2072 }
yasin saplibddc2d72022-02-08 13:10:17 +00002073 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx)
2074 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002075 dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002076 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2077 logger.Debug(ctx, err)
2078 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002079 }
yasin saplibddc2d72022-02-08 13:10:17 +00002080 // Clean up NNI manager's data
2081 _ = dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002082 }
A R Karthick1f85b802019-10-11 05:06:05 +00002083
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002084 // Take one final sweep at cleaning up KV store for the OLT device
2085 // Clean everything at <base-path-prefix>/openolt/<device-id>
2086 kvClient, err := kvstore.NewEtcdClient(ctx, dh.openOLT.KVStoreAddress, rsrcMgr.KvstoreTimeout, log.FatalLevel)
2087 if err == nil {
2088 kvBackend := &db.Backend{
2089 Client: kvClient,
2090 StoreType: dh.openOLT.KVStoreType,
2091 Address: dh.openOLT.KVStoreAddress,
2092 Timeout: rsrcMgr.KvstoreTimeout,
2093 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, dh.cm.Backend.PathPrefix, dh.device.Id)}
2094 _ = kvBackend.DeleteWithPrefix(ctx, "")
2095 }
2096
Devmalya Paul495b94a2019-08-27 19:42:00 -04002097 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302098 dh.onus.Range(func(key interface{}, value interface{}) bool {
2099 dh.onus.Delete(key)
2100 return true
2101 })
2102
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002103 /*Delete discovered ONU map for the device*/
2104 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2105 dh.discOnus.Delete(key)
2106 return true
2107 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002108}
2109
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002110//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002111func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002112 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302113 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002114 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002115 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002116 return nil
2117}
2118
David K. Bainbridge794735f2020-02-11 21:01:37 -08002119func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002120 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002121 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002122 "packet-indication": *packetIn,
2123 "device-id": dh.device.Id,
2124 "packet": hex.EncodeToString(packetIn.Pkt),
2125 })
2126 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002127 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002128 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002129 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002130 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002131 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002132 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002133 "logical-port-num": logicalPortNum,
2134 "device-id": dh.device.Id,
2135 "packet": hex.EncodeToString(packetIn.Pkt),
2136 })
2137 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002138
khenaidoodc2116e2021-10-19 17:33:19 -04002139 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002140 DeviceId: dh.device.Id,
2141 Port: logicalPortNum,
2142 Packet: packetIn.Pkt,
2143 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302144 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002145 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302146 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002147 "device-id": dh.device.Id,
2148 "packet": hex.EncodeToString(packetIn.Pkt),
2149 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002150 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002151
Matteo Scandolo92186242020-06-12 10:54:18 -07002152 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002153 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002154 "packet": hex.EncodeToString(packetIn.Pkt),
2155 "device-id": dh.device.Id,
2156 })
2157 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002158 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002159}
2160
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002161// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002162func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002163 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002164 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002165 "device-id": dh.device.Id,
2166 "egress-port-no": egressPortNo,
2167 "pkt-length": len(packet.Data),
2168 "packet": hex.EncodeToString(packet.Data),
2169 })
2170 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002171
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002172 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002173 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002174 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2175 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302176 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2177 // Do not packet-out lldp packets on uni port.
2178 // ONOS has no clue about uni/nni ports, it just packets out on all
2179 // available ports on the Logical Switch. It should not be interested
2180 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002181 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002182 "device-id": dh.device.Id,
2183 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302184 return nil
2185 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002186 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2187 if innerEthType == 0x8100 {
2188 // q-in-q 802.1ad or 802.1q double tagged packet.
2189 // slice out the outer tag.
2190 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002191 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002192 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002193 "packet-data": hex.EncodeToString(packet.Data),
2194 "device-id": dh.device.Id,
2195 })
2196 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002197 }
2198 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002199 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2200 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2201 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002202
Girish Gowdra9602eb42020-09-09 15:50:39 -07002203 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002204 if err != nil {
2205 // In this case the openolt agent will receive the gemPortID as 0.
2206 // The agent tries to retrieve the gemPortID in this case.
2207 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002208 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002209 "intf-id": intfID,
2210 "onu-id": onuID,
2211 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002212 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302213 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002214 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002215 }
2216
2217 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002218 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002219 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002220 "egress-port-no": egressPortNo,
2221 "intf-id": intfID,
2222 "onu-id": onuID,
2223 "uni-id": uniID,
2224 "gem-port-id": gemPortID,
2225 "packet": hex.EncodeToString(packet.Data),
2226 "device-id": dh.device.Id,
2227 })
2228 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002229
npujarec5762e2020-01-01 14:08:48 +05302230 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302231 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002232 "source": "adapter",
2233 "destination": "onu",
2234 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002235 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002236 "oni-id": onuID,
2237 "uni-id": uniID,
2238 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002239 "packet": hex.EncodeToString(packet.Data),
2240 "device-id": dh.device.Id,
2241 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002242 }
2243 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002244 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002245 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002246 return olterrors.NewErrInvalidValue(log.Fields{
2247 "egress-nni-port": egressPortNo,
2248 "device-id": dh.device.Id,
2249 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002250 }
2251 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002252
Matteo Scandolo92186242020-06-12 10:54:18 -07002253 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002254 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002255 "uplink-pkt": uplinkPkt,
2256 "packet": hex.EncodeToString(packet.Data),
2257 "device-id": dh.device.Id,
2258 })
2259 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002260
npujarec5762e2020-01-01 14:08:48 +05302261 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002262 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2263 "packet": hex.EncodeToString(packet.Data),
2264 "device-id": dh.device.Id,
2265 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002266 }
2267 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002268 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302269 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002270 "egressPortType": egressPortType,
2271 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302272 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002273 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002274 }
2275 return nil
2276}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002277
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002278func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2279 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002280}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302281
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002282func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002283
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302284 // start the heartbeat check towards the OLT.
2285 var timerCheck *time.Timer
2286
2287 for {
2288 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2289 select {
2290 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002291 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002292 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002293 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302294 if timerCheck == nil {
2295 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002296 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302297 }
2298 } else {
2299 if timerCheck != nil {
2300 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002301 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302302 }
2303 timerCheck = nil
2304 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002305 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302306 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302307 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302308 }
2309 cancel()
2310 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002311 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302312 return
2313 }
2314 }
2315}
2316
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002317func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002318 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002319 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002320 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2321 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2322 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2323 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2324 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002325 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002326 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2327 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002328 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302329
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002330 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2331 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002332 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002333 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002334 DeviceId: dh.device.Id,
2335 OperStatus: voltha.OperStatus_UNKNOWN,
2336 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2337 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002338 _ = 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 -04002339 }
khenaidoo106c61a2021-08-11 18:05:46 -04002340
khenaidoodc2116e2021-10-19 17:33:19 -04002341 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002342 DeviceId: dh.device.Id,
2343 PortTypeFilter: 0,
2344 OperStatus: voltha.OperStatus_UNKNOWN,
2345 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002346 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002347 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002348
2349 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002350 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002351 cloned := proto.Clone(device).(*voltha.Device)
2352 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2353 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2354 dh.device = cloned // update local copy of the device
2355 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002356
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002357 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002358 // Stop the Stats collector
2359 dh.stopCollector <- true
2360 // stop the heartbeat check routine
2361 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002362
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002363 dh.lockDevice.RLock()
2364 // Stop the read indication only if it the routine is active
2365 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2366 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2367 // on next execution of the readIndication routine.
2368 if dh.isReadIndicationRoutineActive {
2369 dh.stopIndications <- true
2370 }
2371 dh.lockDevice.RUnlock()
2372
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002373 var wg sync.WaitGroup
2374 wg.Add(1) // for the multicast handler routine
2375 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002376 for _, flMgr := range dh.flowMgr {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002377 wg.Add(1) // for the flow handler routine
2378 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2379 }
2380 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2381 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2382 } else {
2383 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002384 }
2385
Gamze Abakac2c32a62021-03-11 11:44:18 +00002386 //reset adapter reconcile flag
2387 dh.adapterPreviouslyConnected = false
2388
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002389 dh.transitionMap.Handle(ctx, DeviceInit)
2390
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302391 }
2392}
kesavand39e0aa32020-01-28 20:58:50 -05002393
2394// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002395func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2396 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2397 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002398}
2399
2400// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002401func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2402 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2403 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002404}
2405
kdarapu1afeceb2020-02-12 01:38:09 -05002406//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 +00002407func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2408 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002409 if port.GetType() == voltha.Port_ETHERNET_NNI {
2410 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002411 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302412 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302413 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002414 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002415 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002416 }
2417 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002418 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002419 ponIntf := &oop.Interface{IntfId: ponID}
2420 var operStatus voltha.OperStatus_Types
2421 if enablePort {
2422 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302423 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002424
2425 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302426 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002427 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002428 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002429 }
2430 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002431 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002432 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002433 } else {
2434 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302435 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002436 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302437 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002438 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002439 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002440 }
2441 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002442 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002443 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002444 }
khenaidoodc2116e2021-10-19 17:33:19 -04002445 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002446 DeviceId: dh.device.Id,
2447 PortType: voltha.Port_PON_OLT,
2448 PortNo: port.PortNo,
2449 OperStatus: operStatus,
2450 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302451 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302452 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002453 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002454 }
2455 return nil
2456}
2457
kdarapu1afeceb2020-02-12 01:38:09 -05002458//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002459func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002460 // Disable the port and update the oper_port_status to core
2461 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002462 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002463 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002464 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302465 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302466 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002467 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002468 }
2469 }
2470 }
2471 return nil
2472}
2473
2474//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002475func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2476 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2477 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002478 if port.Type == voltha.Port_ETHERNET_NNI {
2479 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002480 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002481 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002482 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002483 }
2484 }
2485 if port.Type == voltha.Port_PON_OLT {
2486 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002487 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002488 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002489 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002490 }
2491 }
2492 }
2493}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002494
2495// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002496func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002497 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdrab4c33302022-03-18 15:07:38 -07002498 if dh.getDeviceDeletionInProgressFlag() {
2499 // Given that the OLT device itself is getting deleted, everything will be cleaned up in the DB and the OLT
2500 // will reboot, so everything will be reset on the pOLT too.
2501 logger.Infow(ctx, "olt-device-delete-in-progress-not-handling-child-device-lost",
2502 log.Fields{"parent-device-id": dh.device.Id, "pon-port": pPortNo, "onuID": onuID, "onuSN": onuSn})
2503 return nil
2504 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002505 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002506 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002507
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002508 var sn *oop.SerialNumber
2509 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002510 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302511 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002512 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302513 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002514 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002515 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002516
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002517 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002518 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00002519 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002520 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2521 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2522 "device-id": dh.device.Id,
2523 "intf-id": intfID,
2524 "onuID": onuID,
2525 "err": err})
2526 } else {
2527 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
yasin saplie87d4bd2021-12-06 09:04:03 +00002528 // Delete flows from device before schedulers and queue
2529 // Clear flowids for gem cache.
2530 removedFlows := []uint64{}
2531 for _, gem := range onuGem.GemPorts {
2532 if flowIDs, err := dh.resourceMgr[intfID].GetFlowIDsForGem(ctx, gem); err == nil {
2533 for _, flowID := range flowIDs {
2534 //multiple gem port can have the same flow id
2535 //it is better to send only one flowRemove request to the agent
2536 var alreadyRemoved bool
2537 for _, removedFlowID := range removedFlows {
2538 if removedFlowID == flowID {
2539 logger.Debugw(ctx, "flow-is-already-removed-due-to-another-gem", log.Fields{"flowID": flowID})
2540 alreadyRemoved = true
2541 break
2542 }
2543 }
2544 if !alreadyRemoved {
2545 flow := &oop.Flow{FlowId: flowID}
2546 if err := dh.flowMgr[intfID].removeFlowFromDevice(ctx, flow, flowID); err != nil {
2547 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{
2548 "device-id": dh.device.Id,
2549 "onu-device": onu,
2550 "err": err})
2551 }
2552 removedFlows = appendUnique64bit(removedFlows, flowID)
2553 }
2554 }
2555 }
2556 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
2557 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002558 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2559 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2560 "device-id": dh.device.Id,
2561 "onu-device": onu,
2562 "err": err})
2563 }
yasin saplibddc2d72022-02-08 13:10:17 +00002564 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002565 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2566 "intf-id": intfID,
2567 "onu-device": onu,
2568 "onu-gem": onuGem,
2569 "err": err})
2570 //Not returning error on cleanup.
2571 }
2572 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302573
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002574 }
yasin saplibddc2d72022-02-08 13:10:17 +00002575 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002576 dh.onus.Delete(onuKey)
2577 dh.discOnus.Delete(onuSn)
2578
2579 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002580 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302581 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302582 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002583 "onu-id": onuID}, err).Log()
2584 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002585
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002586 return nil
2587}
Girish Gowdracefae192020-03-19 18:14:10 -07002588
2589func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002590 for _, field := range flow_utils.GetOfbFields(flow) {
2591 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002592 return field.GetPort()
2593 }
2594 }
2595 return InvalidPort
2596}
2597
2598func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002599 for _, action := range flow_utils.GetActions(flow) {
2600 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002601 if out := action.GetOutput(); out != nil {
2602 return out.GetPort()
2603 }
2604 }
2605 }
2606 return InvalidPort
2607}
2608
Girish Gowdracefae192020-03-19 18:14:10 -07002609func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2610 inPort := getInPortFromFlow(flow)
2611 outPort := getOutPortFromFlow(flow)
2612
2613 if inPort == InvalidPort || outPort == InvalidPort {
2614 return inPort, outPort
2615 }
2616
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002617 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002618 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002619 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002620 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002621 return uniPort, outPort
2622 }
2623 }
2624 } else {
2625 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002626 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002627 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002628 return inPort, uniPort
2629 }
2630 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002631 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002632 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002633 return uniPort, outPort
2634 }
2635 }
2636 }
2637
2638 return InvalidPort, InvalidPort
2639}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002640
2641func extractOmciTransactionID(omciPkt []byte) uint16 {
2642 if len(omciPkt) > 3 {
2643 d := omciPkt[0:2]
2644 transid := binary.BigEndian.Uint16(d)
2645 return transid
2646 }
2647 return 0
2648}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002649
2650// StoreOnuDevice stores the onu parameters to the local cache.
2651func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2652 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2653 dh.onus.Store(onuKey, onuDevice)
2654}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002655
khenaidoodc2116e2021-10-19 17:33:19 -04002656func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002657 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002658 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002659 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002660 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002661 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002662 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002663 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002664 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2665 return nil, err
2666 }
2667 ID = device.ProxyAddress.GetOnuId()
2668 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2669 valueparam.Onu = &Onu
2670 valueparam.Value = value
2671
2672 // This API is unsupported until agent patch is added
2673 resp.Unsupported = uint32(value)
2674 _ = ctx
2675
2676 // Uncomment this code once agent changes are complete and tests
2677 /*
2678 resp, err = dh.Client.GetValue(ctx, valueparam)
2679 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002680 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002681 return nil, err
2682 }
2683 */
2684
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002685 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 -08002686 return resp, nil
2687}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002688
yasin saplid0566272021-12-21 09:10:30 +00002689func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
2690 // Default to NNI
2691 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07002692 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002693 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002694 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002695 }
2696 return intfID
2697}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002698
Mahir Gunyelb0046752021-02-26 13:51:05 -08002699func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2700 dh.perPonOnuIndicationChannelLock.Lock()
2701 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2702 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002703 return ch.indicationChannel
2704 }
2705 channels := onuIndicationChannels{
2706 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002707 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002708 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002709 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002710 stopChannel: make(chan struct{}),
2711 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002712 dh.perPonOnuIndicationChannel[intfID] = channels
2713 dh.perPonOnuIndicationChannelLock.Unlock()
2714 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002715 return channels.indicationChannel
2716
2717}
2718
Mahir Gunyelb0046752021-02-26 13:51:05 -08002719func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2720 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2721 dh.perPonOnuIndicationChannelLock.Lock()
2722 defer dh.perPonOnuIndicationChannelLock.Unlock()
2723 for _, v := range dh.perPonOnuIndicationChannel {
2724 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002725 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002726 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002727}
2728
Mahir Gunyelb0046752021-02-26 13:51:05 -08002729func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2730 ind := onuIndicationMsg{
2731 ctx: ctx,
2732 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002733 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002734 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002735 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002736 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002737}
2738
Mahir Gunyelb0046752021-02-26 13:51:05 -08002739func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002740 for {
2741 select {
2742 // process one indication per onu, before proceeding to the next one
2743 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08002744 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002745 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08002746 "ind": indication})
2747 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002748 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002749 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002750 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2751 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002752 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002753 }
2754 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002755 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002756 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2757 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002758 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002759 }
2760 }
2761 case <-onuChannels.stopChannel:
2762 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2763 close(onuChannels.indicationChannel)
2764 return
2765 }
2766 }
2767}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002768
2769// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2770// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04002771func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002772 if dh.getDeviceDeletionInProgressFlag() {
2773 // The device itself is going to be reset as part of deletion. So nothing to be done.
2774 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2775 return nil
2776 }
2777
Girish Gowdra491a9c62021-01-06 16:43:07 -08002778 // Step1 : Fill McastFlowOrGroupControlBlock
2779 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2780 // Step3 : Wait on response channel for response
2781 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002782 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002783 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2784 errChan := make(chan error)
2785 var groupID uint32
2786 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2787 ctx: ctx,
2788 flowOrGroupAction: action,
2789 flow: flow,
2790 group: group,
2791 errChan: &errChan,
2792 }
2793 if flow != nil {
2794 groupID = flow_utils.GetGroup(flow)
2795 } else if group != nil {
2796 groupID = group.Desc.GroupId
2797 } else {
2798 return errors.New("flow-and-group-both-nil")
2799 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002800 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2801 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2802 // Derive the appropriate go routine to handle the request by a simple module operation.
2803 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2804 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2805 // Wait for handler to return error value
2806 err := <-errChan
2807 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2808 return err
2809 }
2810 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2811 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002812}
2813
2814// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002815func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002816 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002817 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002818 // block on the channel to receive an incoming mcast flow/group
2819 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002820 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2821 if mcastFlowOrGroupCb.flow != nil {
2822 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2823 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2824 log.Fields{"device-id": dh.device.Id,
2825 "flowToAdd": mcastFlowOrGroupCb.flow})
2826 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2827 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2828 // Pass the return value over the return channel
2829 *mcastFlowOrGroupCb.errChan <- err
2830 } else { // flow remove
2831 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2832 log.Fields{"device-id": dh.device.Id,
2833 "flowToRemove": mcastFlowOrGroupCb.flow})
2834 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2835 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2836 // Pass the return value over the return channel
2837 *mcastFlowOrGroupCb.errChan <- err
2838 }
2839 } else { // mcast group
2840 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2841 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2842 log.Fields{"device-id": dh.device.Id,
2843 "groupToAdd": mcastFlowOrGroupCb.group})
2844 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2845 // Pass the return value over the return channel
2846 *mcastFlowOrGroupCb.errChan <- err
2847 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2848 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2849 log.Fields{"device-id": dh.device.Id,
2850 "groupToModify": mcastFlowOrGroupCb.group})
2851 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2852 // Pass the return value over the return channel
2853 *mcastFlowOrGroupCb.errChan <- err
2854 } else { // group remove
2855 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2856 log.Fields{"device-id": dh.device.Id,
2857 "groupToRemove": mcastFlowOrGroupCb.group})
2858 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2859 // Pass the return value over the return channel
2860 *mcastFlowOrGroupCb.errChan <- err
2861 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002862 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002863 case <-stopHandler:
2864 dh.mcastHandlerRoutineActive[routineIndex] = false
2865 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08002866 }
2867 }
2868}
kesavand62126212021-01-12 04:56:06 -05002869
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002870// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002871func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002872 for i, v := range dh.stopMcastHandlerRoutine {
2873 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002874 select {
2875 case v <- true:
2876 case <-time.After(time.Second * 5):
2877 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
2878 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002879 }
2880 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002881 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002882 logger.Debug(ctx, "stopped all mcast handler routines")
2883}
2884
kesavand62126212021-01-12 04:56:06 -05002885func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2886
2887 singleValResp := extension.SingleGetValueResponse{
2888 Response: &extension.GetValueResponse{
2889 Response: &extension.GetValueResponse_PortCoutners{
2890 PortCoutners: &extension.GetOltPortCountersResponse{},
2891 },
2892 },
2893 }
2894
2895 errResp := func(status extension.GetValueResponse_Status,
2896 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2897 return &extension.SingleGetValueResponse{
2898 Response: &extension.GetValueResponse{
2899 Status: status,
2900 ErrReason: reason,
2901 },
2902 }
2903 }
2904
2905 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2906 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2907 //send error response
2908 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2909 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2910 }
2911 statIndChn := make(chan bool, 1)
2912 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2913 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2914 //request openOlt agent to send the the port statistics indication
2915
2916 go func() {
2917 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2918 if err != nil {
2919 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2920 }
2921 }()
2922 select {
2923 case <-statIndChn:
2924 //indication received for ports stats
2925 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2926 case <-time.After(oltPortInfoTimeout * time.Second):
2927 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2928 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2929 case <-ctx.Done():
2930 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2931 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2932 }
2933 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2934 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002935 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05002936 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2937 cmnni := dh.portStats.collectNNIMetrics(intfID)
2938 if cmnni == nil {
2939 //TODO define the error reason
2940 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2941 }
2942 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2943 return &singleValResp
2944
2945 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2946 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002947 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05002948 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2949 cmpon := dh.portStats.collectPONMetrics(intfID)
2950 if cmpon == nil {
2951 //TODO define the error reason
2952 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2953 }
2954 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2955 return &singleValResp
2956 }
2957 }
2958 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2959}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302960
2961func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2962
2963 singleValResp := extension.SingleGetValueResponse{
2964 Response: &extension.GetValueResponse{
2965 Response: &extension.GetValueResponse_OnuPonCounters{
2966 OnuPonCounters: &extension.GetOnuCountersResponse{},
2967 },
2968 },
2969 }
2970
2971 errResp := func(status extension.GetValueResponse_Status,
2972 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2973 return &extension.SingleGetValueResponse{
2974 Response: &extension.GetValueResponse{
2975 Status: status,
2976 ErrReason: reason,
2977 },
2978 }
2979 }
2980 intfID := onuPonInfo.IntfId
2981 onuID := onuPonInfo.OnuId
2982 onuKey := dh.formOnuKey(intfID, onuID)
2983
2984 if _, ok := dh.onus.Load(onuKey); !ok {
2985 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2986 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2987 }
2988 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2989 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2990 if cmnni == nil {
2991 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2992 }
2993 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2994 return &singleValResp
2995
2996}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002997
2998func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2999
3000 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
3001 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
3002 if err != nil {
3003 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
3004 return generateSingleGetValueErrorResponse(err)
3005 }
3006 return &extension.SingleGetValueResponse{
3007 Response: &extension.GetValueResponse{
3008 Status: extension.GetValueResponse_OK,
3009 Response: &extension.GetValueResponse_RxPower{
3010 RxPower: &extension.GetRxPowerResponse{
3011 IntfId: rxPowerRequest.IntfId,
3012 OnuId: rxPowerRequest.OnuId,
3013 Status: rxPower.Status,
3014 FailReason: rxPower.FailReason.String(),
3015 RxPower: rxPower.RxPowerMeanDbm,
3016 },
3017 },
3018 },
3019 }
3020}
3021
3022func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
3023 errResp := func(status extension.GetValueResponse_Status,
3024 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
3025 return &extension.SingleGetValueResponse{
3026 Response: &extension.GetValueResponse{
3027 Status: status,
3028 ErrReason: reason,
3029 },
3030 }
3031 }
3032
3033 if err != nil {
3034 if e, ok := status.FromError(err); ok {
3035 switch e.Code() {
3036 case codes.Internal:
3037 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
3038 case codes.DeadlineExceeded:
3039 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
3040 case codes.Unimplemented:
3041 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
3042 case codes.NotFound:
3043 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3044 }
3045 }
3046 }
3047
3048 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3049}
khenaidoo106c61a2021-08-11 18:05:46 -04003050
3051/*
3052Helper functions to communicate with Core
3053*/
3054
3055func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3056 cClient, err := dh.coreClient.GetCoreServiceClient()
3057 if err != nil || cClient == nil {
3058 return nil, err
3059 }
3060 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3061 defer cancel()
3062 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3063}
3064
khenaidoodc2116e2021-10-19 17:33:19 -04003065func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003066 cClient, err := dh.coreClient.GetCoreServiceClient()
3067 if err != nil || cClient == nil {
3068 return nil, err
3069 }
3070 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3071 defer cancel()
3072 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3073}
3074
khenaidoodc2116e2021-10-19 17:33:19 -04003075func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003076 cClient, err := dh.coreClient.GetCoreServiceClient()
3077 if err != nil || cClient == nil {
3078 return err
3079 }
3080 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3081 defer cancel()
3082 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3083 return err
3084}
3085
3086func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3087 cClient, err := dh.coreClient.GetCoreServiceClient()
3088 if err != nil || cClient == nil {
3089 return nil, err
3090 }
3091 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3092 defer cancel()
3093 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3094}
3095
3096func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3097 cClient, err := dh.coreClient.GetCoreServiceClient()
3098 if err != nil || cClient == nil {
3099 return nil, err
3100 }
3101 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3102 defer cancel()
3103 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3104}
3105
3106func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3107 cClient, err := dh.coreClient.GetCoreServiceClient()
3108 if err != nil || cClient == nil {
3109 return err
3110 }
3111 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3112 defer cancel()
3113 _, err = cClient.DeviceUpdate(subCtx, device)
3114 return err
3115}
3116
khenaidoodc2116e2021-10-19 17:33:19 -04003117func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003118 cClient, err := dh.coreClient.GetCoreServiceClient()
3119 if err != nil || cClient == nil {
3120 return nil, err
3121 }
3122 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3123 defer cancel()
3124 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3125}
3126
khenaidoodc2116e2021-10-19 17:33:19 -04003127func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003128 cClient, err := dh.coreClient.GetCoreServiceClient()
3129 if err != nil || cClient == nil {
3130 return err
3131 }
3132 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3133 defer cancel()
3134 _, err = cClient.SendPacketIn(subCtx, pkt)
3135 return err
3136}
3137
3138func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3139 cClient, err := dh.coreClient.GetCoreServiceClient()
3140 if err != nil || cClient == nil {
3141 return err
3142 }
3143 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3144 defer cancel()
3145 _, err = cClient.PortCreated(subCtx, port)
3146 return err
3147}
3148
khenaidoodc2116e2021-10-19 17:33:19 -04003149func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003150 cClient, err := dh.coreClient.GetCoreServiceClient()
3151 if err != nil || cClient == nil {
3152 return err
3153 }
3154 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3155 defer cancel()
3156 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3157 return err
3158}
3159
khenaidoodc2116e2021-10-19 17:33:19 -04003160func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003161 cClient, err := dh.coreClient.GetCoreServiceClient()
3162 if err != nil || cClient == nil {
3163 return err
3164 }
3165 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3166 defer cancel()
3167 _, err = cClient.PortStateUpdate(subCtx, portState)
3168 return err
3169}
3170
khenaidoodc2116e2021-10-19 17:33:19 -04003171func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003172 cClient, err := dh.coreClient.GetCoreServiceClient()
3173 if err != nil || cClient == nil {
3174 return nil, err
3175 }
3176 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3177 defer cancel()
3178 return cClient.GetDevicePort(subCtx, portFilter)
3179}
3180
3181/*
3182Helper functions to communicate with child adapter
3183*/
3184
khenaidoodc2116e2021-10-19 17:33:19 -04003185func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003186 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3187 if err != nil || aClient == nil {
3188 return err
3189 }
3190 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3191 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3192 defer cancel()
3193 _, err = aClient.OmciIndication(subCtx, response)
3194 return err
3195}
3196
khenaidoodc2116e2021-10-19 17:33:19 -04003197func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003198 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3199 if err != nil || aClient == nil {
3200 return err
3201 }
3202 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3203 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3204 defer cancel()
3205 _, err = aClient.OnuIndication(subCtx, onuInd)
3206 return err
3207}
3208
khenaidoodc2116e2021-10-19 17:33:19 -04003209func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003210 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3211 if err != nil || aClient == nil {
3212 return err
3213 }
3214 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3215 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3216 defer cancel()
3217 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3218 return err
3219}
3220
khenaidoodc2116e2021-10-19 17:33:19 -04003221func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003222 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3223 if err != nil || aClient == nil {
3224 return err
3225 }
3226 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3227 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3228 defer cancel()
3229 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3230 return err
3231}
3232
khenaidoodc2116e2021-10-19 17:33:19 -04003233func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003234 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3235 if err != nil || aClient == nil {
3236 return err
3237 }
3238 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3239 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3240 defer cancel()
3241 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3242 return err
3243}
3244
3245/*
3246Helper functions for remote communication
3247*/
3248
3249// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3250// supports is deleted
3251func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3252 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3253
3254 dh.lockChildAdapterClients.Lock()
3255 defer dh.lockChildAdapterClients.Unlock()
3256 if _, ok := dh.childAdapterClients[endpoint]; ok {
3257 // Already set
3258 return nil
3259 }
3260
3261 // Setup child's adapter grpc connection
3262 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003263 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3264 dh.cfg.AdapterEndpoint,
3265 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05003266 "onu_inter_adapter_service.OnuInterAdapterService",
3267 dh.onuInterAdapterRestarted,
3268 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003269 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3270 return err
3271 }
khenaidooefff76e2021-12-15 16:51:30 -05003272 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003273
3274 // Wait until we have a connection to the child adapter.
3275 // Unlimited retries or until context expires
3276 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3277 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3278 for {
3279 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3280 if err == nil && client != nil {
3281 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3282 break
3283 }
3284 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3285 // Backoff
3286 if err = backoff.Backoff(subCtx); err != nil {
3287 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3288 break
3289 }
3290 }
3291 return nil
3292}
3293
khenaidoodc2116e2021-10-19 17:33:19 -04003294func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003295
3296 // First check from cache
3297 dh.lockChildAdapterClients.RLock()
3298 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3299 dh.lockChildAdapterClients.RUnlock()
3300 return cgClient.GetOnuInterAdapterServiceClient()
3301 }
3302 dh.lockChildAdapterClients.RUnlock()
3303
3304 // Set the child connection - can occur on restarts
3305 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3306 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3307 cancel()
3308 if err != nil {
3309 return nil, err
3310 }
3311
3312 // Get the child client now
3313 dh.lockChildAdapterClients.RLock()
3314 defer dh.lockChildAdapterClients.RUnlock()
3315 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3316 return cgClient.GetOnuInterAdapterServiceClient()
3317 }
3318 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3319}
3320
3321func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3322 dh.lockChildAdapterClients.Lock()
3323 defer dh.lockChildAdapterClients.Unlock()
3324 for key, client := range dh.childAdapterClients {
3325 client.Stop(ctx)
3326 delete(dh.childAdapterClients, key)
3327 }
3328}
3329
khenaidooefff76e2021-12-15 16:51:30 -05003330// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
3331func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
3332 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003333 return nil
3334}
3335
khenaidooefff76e2021-12-15 16:51:30 -05003336// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
3337func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
3338 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003339 return nil
3340 }
khenaidooefff76e2021-12-15 16:51:30 -05003341 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04003342}
Girish Gowdra950326e2021-11-05 12:43:24 -07003343
3344func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3345 dh.lockDevice.Lock()
3346 defer dh.lockDevice.Unlock()
3347 dh.isDeviceDeletionInProgress = flag
3348}
3349
3350func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3351 dh.lockDevice.RLock()
3352 defer dh.lockDevice.RUnlock()
3353 return dh.isDeviceDeletionInProgress
3354}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003355
3356// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3357// Returns false if waiting timed out.
3358func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3359 c := make(chan struct{})
3360 go func() {
3361 defer close(c)
3362 wg.Wait()
3363 }()
3364 select {
3365 case <-c:
3366 return true // completed normally
3367 case <-time.After(timeout):
3368 return false // timed out
3369 }
3370}