blob: 140158ad25477cb1462d66726e7385ff24407a21 [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"
26 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
khenaidoo106c61a2021-08-11 18:05:46 -040033 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040034
Matteo Scandolo945e4012019-12-12 14:16:11 -080035 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070036 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000037 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
38 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040039 "github.com/opencord/voltha-lib-go/v7/pkg/config"
40 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
41 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
42 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070043 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040044 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080045
khenaidoo106c61a2021-08-11 18:05:46 -040046 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053047 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080048 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040049 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040050 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040051 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040052 "github.com/opencord/voltha-protos/v5/go/health"
53 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
54 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040055 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
56 oop "github.com/opencord/voltha-protos/v5/go/openolt"
57 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070058 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040059 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040060 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053061)
62
salmansiddiqui7ac62132019-08-22 03:58:50 +000063// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040064const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080065 InvalidPort = 0xffffffff
66 MaxNumOfGroupHandlerChannels = 256
67
68 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
69 McastFlowOrGroupModify = "McastFlowOrGroupModify"
70 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050071 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010072
73 defaultPortSpeedMbps = 1000
Manikkaraj kb1d51442019-07-23 10:41:02 -040074)
75
Phaneendra Manda4c62c802019-03-06 21:37:49 +053076//DeviceHandler will interact with the OLT device.
77type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040078 cm *config.ConfigManager
79 device *voltha.Device
80 cfg *conf.AdapterFlags
81 coreClient *vgrpc.Client
82 childAdapterClients map[string]*vgrpc.Client
83 lockChildAdapterClients sync.RWMutex
84 EventProxy eventif.EventProxy
85 openOLT *OpenOLT
86 exitChannel chan int
87 lockDevice sync.RWMutex
88 Client oop.OpenoltClient
89 transitionMap *TransitionMap
90 clientCon *grpc.ClientConn
91 flowMgr []*OpenOltFlowMgr
92 groupMgr *OpenOltGroupMgr
93 eventMgr *OpenOltEventMgr
94 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070095
96 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053097
Girish Gowdra3ab6d212020-03-24 17:33:15 -070098 discOnus sync.Map
99 onus sync.Map
100 portStats *OpenOltStatisticsMgr
101 metrics *pmmetrics.PmMetrics
102 stopCollector chan bool
103 stopHeartbeatCheck chan bool
104 activePorts sync.Map
105 stopIndications chan bool
106 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700107
Mahir Gunyelb0046752021-02-26 13:51:05 -0800108 totalPonPorts uint32
109 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
110 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800111
112 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
113 // 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 -0700114 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
115 stopMcastHandlerRoutine []chan bool
116 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000117
118 adapterPreviouslyConnected bool
119 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700120
121 isDeviceDeletionInProgress bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700122}
123
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700124//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700125type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400126 deviceID string
127 deviceType string
128 serialNumber string
129 onuID uint32
130 intfID uint32
131 proxyDeviceID string
132 losRaised bool
133 rdiRaised bool
134 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700135}
136
Mahir Gunyelb0046752021-02-26 13:51:05 -0800137type onuIndicationMsg struct {
138 ctx context.Context
139 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800140}
141
142type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800143 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800144 stopChannel chan struct{}
145}
146
Girish Gowdra491a9c62021-01-06 16:43:07 -0800147//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
148//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
149//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
150//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
151type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400152 ctx context.Context // Flow/group handler context
153 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
154 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
155 group *of.OfpGroupEntry // Group message (can be nil or valid group)
156 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800157}
158
Naga Manjunath7615e552019-10-11 22:35:47 +0530159var pmNames = []string{
160 "rx_bytes",
161 "rx_packets",
162 "rx_mcast_packets",
163 "rx_bcast_packets",
164 "tx_bytes",
165 "tx_packets",
166 "tx_mcast_packets",
167 "tx_bcast_packets",
168}
169
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700170//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400171func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700172 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700173 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700174 device.deviceType = deviceTp
175 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700176 device.onuID = onuID
177 device.intfID = intfID
178 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530179 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400180 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700181 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530182}
183
184//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400185func 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 -0700186 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800187 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400188 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400189 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700190 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700191 dh.device = cloned
192 dh.openOLT = adapter
Girish Gowdraae56c722021-11-22 14:31:11 -0800193 dh.exitChannel = make(chan int, 1) // TODO: Why buffered?
cuilin20187b2a8c32019-03-26 19:52:28 -0700194 dh.lockDevice = sync.RWMutex{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800195 dh.stopCollector = make(chan bool, 2) // TODO: Why buffered?
196 dh.stopHeartbeatCheck = make(chan bool, 2) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530197 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 -0500198 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800199 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800200 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400201 dh.childAdapterClients = make(map[string]*vgrpc.Client)
202 dh.cfg = cfg
Girish Gowdra491a9c62021-01-06 16:43:07 -0800203 // Create a slice of buffered channels for handling concurrent mcast flow/group.
204 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700205 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
206 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800207 for i := range dh.incomingMcastFlowOrGroup {
208 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800209 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800210 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
211 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
212 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
213 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700214 dh.mcastHandlerRoutineActive[i] = true
215 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800216 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700217 //TODO initialize the support classes.
218 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530219}
220
221// start save the device to the data model
222func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700223 dh.lockDevice.Lock()
224 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000225 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700226 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000227 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530228}
229
230// stop stops the device dh. Not much to do for now
231func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700232 dh.lockDevice.Lock()
233 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000234 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700235 dh.exitChannel <- 1
khenaidoo106c61a2021-08-11 18:05:46 -0400236
Neha Sharma96b7bf22020-06-15 10:37:32 +0000237 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530238}
239
ssiddiqui04386ee2021-08-23 21:58:25 +0530240func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
241 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
242 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
243 if pooledIntfID == intfID {
244 return resourceRanges.GetTechnology()
245 }
246 }
247 }
248 return ""
249}
250
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400251func macifyIP(ip net.IP) string {
252 if len(ip) > 0 {
253 oct1 := strconv.FormatInt(int64(ip[12]), 16)
254 oct2 := strconv.FormatInt(int64(ip[13]), 16)
255 oct3 := strconv.FormatInt(int64(ip[14]), 16)
256 oct4 := strconv.FormatInt(int64(ip[15]), 16)
257 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
258 }
259 return ""
260}
261
Neha Sharma96b7bf22020-06-15 10:37:32 +0000262func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400263 var genmac string
264 var addr net.IP
265 var ips []string
266 var err error
267
Neha Sharma96b7bf22020-06-15 10:37:32 +0000268 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400269
270 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000271 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400272
273 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000274 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400275 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000276 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400277 }
278 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000279 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530280 log.Fields{"host": ips[0],
281 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400282 return genmac, nil
283 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000284 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400285 }
286
287 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000288 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530289 log.Fields{"host": host,
290 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400291 return genmac, nil
292}
293
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530294func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700295 slist := strings.Split(mac, ":")
296 result := make([]uint32, len(slist))
297 var err error
298 var tmp int64
299 for index, val := range slist {
300 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
301 return []uint32{1, 2, 3, 4, 5, 6}
302 }
303 result[index] = uint32(tmp)
304 }
305 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530306}
307
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700308//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 -0800309func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530310
David K. Bainbridge794735f2020-02-11 21:01:37 -0800311 switch portType {
312 case voltha.Port_ETHERNET_NNI:
313 return fmt.Sprintf("nni-%d", portNum), nil
314 case voltha.Port_PON_OLT:
315 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700316 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800317
Girish Kumarf26e4882020-03-05 06:49:10 +0000318 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530319}
320
Elia Battiston596406d2022-02-02 12:19:00 +0100321func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
322 if speedMbps == 0 {
323 //In case it was not set in the indication
324 //and no other value was provided
325 speedMbps = defaultPortSpeedMbps
326 }
327
328 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
329 switch speedMbps {
330 case 1000000:
331 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
332 case 100000:
333 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
334 case 40000:
335 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
336 case 10000:
337 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
338 case 1000:
339 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
340 case 100:
341 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
342 case 10:
343 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
344 }
345
346 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
347
348 port := &of.OfpPort{
349 HwAddr: macAddressToUint32Array(macAddress),
350 Config: 0,
351 State: uint32(of.OfpPortState_OFPPS_LIVE),
352 Curr: capacity,
353 Advertised: capacity,
354 Peer: capacity,
355 CurrSpeed: speedMbps * 1000, //kbps
356 MaxSpeed: speedMbps * 1000, //kbps
357 }
358
359 return port
360}
361
362func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000363 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700364 if state == "up" {
365 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500366 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500367 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700368 } else {
369 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500370 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700371 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700372 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400373 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800374 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000375 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400376 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500377
khenaidoo106c61a2021-08-11 18:05:46 -0400378 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400379 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400380 DeviceId: dh.device.Id,
381 Port: portNum,
382 })
383 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000384 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400385 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400386 DeviceId: dh.device.Id,
387 PortType: portType,
388 PortNo: portNum,
389 OperStatus: operStatus})
390 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400391 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
392 "device-id": dh.device.Id,
393 "port-type": portType,
394 "port-number": portNum,
395 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500396 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400397 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500398 }
khenaidoo106c61a2021-08-11 18:05:46 -0400399
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400400 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400401 port = &voltha.Port{
402 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700403 PortNo: portNum,
404 Label: label,
405 Type: portType,
406 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100407 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700408 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000409 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700410 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400411 err = dh.createPortInCore(ctx, port)
412 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000413 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800414 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000415 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400416 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000417 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530418 return nil
419}
420
Kent Hagermane6ff1012020-07-14 15:07:53 -0400421func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400422 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530423 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400424 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
425 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530426 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800427 dh.lockDevice.Lock()
428 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530429 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530430}
431
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700432// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530433// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800434func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000435 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700436 defer func() {
437 dh.lockDevice.Lock()
438 dh.isReadIndicationRoutineActive = false
439 dh.lockDevice.Unlock()
440 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700441 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700442 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700443 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700444 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400445
David Bainbridgef5879ca2019-12-13 21:17:54 +0000446 // Create an exponential backoff around re-enabling indications. The
447 // maximum elapsed time for the back off is set to 0 so that we will
448 // continue to retry. The max interval defaults to 1m, but is set
449 // here for code clarity
450 indicationBackoff := backoff.NewExponentialBackOff()
451 indicationBackoff.MaxElapsedTime = 0
452 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700453
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700454 dh.lockDevice.Lock()
455 dh.isReadIndicationRoutineActive = true
456 dh.lockDevice.Unlock()
457
Girish Gowdra3f974912020-03-23 20:35:18 -0700458Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700459 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400460 select {
461 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000462 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700463 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400464 default:
465 indication, err := indications.Recv()
466 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000467 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530468 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530469 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400470 // Use an exponential back off to prevent getting into a tight loop
471 duration := indicationBackoff.NextBackOff()
472 if duration == backoff.Stop {
473 // If we reach a maximum then warn and reset the backoff
474 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000475 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530476 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530477 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400478 indicationBackoff.Reset()
479 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700480
481 // On failure process a backoff timer while watching for stopIndications
482 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700483 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700484 select {
485 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000486 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700487 if !backoffTimer.Stop() {
488 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700489 }
490 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700491 case <-backoffTimer.C:
492 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700493 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700494 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
495 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400496 }
497 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000498 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530499 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000500 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530501 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530502 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700503 // Close the stream, and re-initialize it
504 if err = indications.CloseSend(); err != nil {
505 // Ok to ignore here, because we landed here due to a problem on the stream
506 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000507 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530508 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530509 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700510 }
Matteo Scandolof16389e2021-05-18 00:47:08 +0000511 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700512 return err
513 }
514 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400515 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530516 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400517 // Reset backoff if we have a successful receive
518 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400519 // When OLT is admin down, ignore all indications.
Girish Gowdra852ad912021-05-04 00:05:50 -0700520 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000521 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530522 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530523 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400524 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400525 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400526 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700527 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700528 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700529 // Close the send stream
530 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700531
Girish Gowdra3f974912020-03-23 20:35:18 -0700532 return nil
533}
534
535func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700536 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700537 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
538 if err != nil {
539 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
540 }
541 if indications == nil {
542 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
543 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700544 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700545 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400546}
547
548// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
549func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
550 switch indication.Data.(type) {
551 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
552 return true
553
554 default:
555 return false
556 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700557}
558
David K. Bainbridge794735f2020-02-11 21:01:37 -0800559func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700560 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000561 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530562 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700563 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530564 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700565 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000566 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000567 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530568 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000569 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800570 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000571 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800572 }
573 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700574}
575
David K. Bainbridge794735f2020-02-11 21:01:37 -0800576// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530577func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700578 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700579 switch indication.Data.(type) {
580 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000581 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
582 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700583 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 -0800584 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400585 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800586 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700587 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000588 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
589 defer span.Finish()
590
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700591 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800592 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100593 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400594 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800595 }
596 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000597 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700598 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000599 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
600 defer span.Finish()
601
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700602 intfOperInd := indication.GetIntfOperInd()
603 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800604 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100605 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400606 _ = 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 -0800607 }
608 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609 } else if intfOperInd.GetType() == "pon" {
610 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
611 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800612 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100613 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400614 _ = 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 -0800615 }
616 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000617 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700618 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000619 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530620 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530621 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000623 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
624 defer span.Finish()
625
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700626 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000627 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800628 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800629 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700630 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000631 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
632 defer span.Finish()
633
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700634 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000635 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800636 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800637 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700638 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000639 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
640 defer span.Finish()
641
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700642 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000643 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 -0800644 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000645 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400646 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800647 }
648 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000650 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
651 defer span.Finish()
652
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700653 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000654 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700655 "intf-type": pktInd.IntfId,
656 "intf-id": pktInd.IntfId,
657 "gem-port-id": pktInd.GemportId,
658 "port-no": pktInd.PortNo,
659 "device-id": dh.device.Id,
660 })
661
662 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000663 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700664 "intf-type": pktInd.IntfId,
665 "intf-id": pktInd.IntfId,
666 "gem-port-id": pktInd.GemportId,
667 "port-no": pktInd.PortNo,
668 "packet": hex.EncodeToString(pktInd.Pkt),
669 "device-id": dh.device.Id,
670 })
671 }
672
David K. Bainbridge794735f2020-02-11 21:01:37 -0800673 go func() {
674 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400675 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800676 }
677 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700678 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000679 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
680 defer span.Finish()
681
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700682 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700683 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700684 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000685 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
686 defer span.Finish()
687
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700688 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000689 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700690 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000691 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
692 defer span.Finish()
693
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700694 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000695 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
696 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700697 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530698}
699
700// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530701func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530702 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000703 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530704
Girish Gowdra618fa572021-09-01 17:19:29 -0700705 // instantiate the mcast handler routines.
706 for i := range dh.incomingMcastFlowOrGroup {
707 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
708 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
709 if !dh.mcastHandlerRoutineActive[i] {
710 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
711 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
712 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
713 // for incoming mcast flow/group to be processed serially.
714 dh.mcastHandlerRoutineActive[i] = true
715 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
716 }
717 }
718
Girish Gowdru0c588b22019-04-23 23:24:56 -0400719 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400720 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400721 DeviceId: dh.device.Id,
722 OperStatus: voltha.OperStatus_ACTIVE,
723 ConnStatus: voltha.ConnectStatus_REACHABLE,
724 }); err != nil {
725 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400726 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000727
728 //Clear olt communication failure event
729 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
730 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700731 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000732 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
733
Gamze Abakac2c32a62021-03-11 11:44:18 +0000734 //check adapter and agent reconcile status
735 //reboot olt if needed (olt disconnection case)
736 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
737 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
738 log.Fields{
739 "device-id": dh.device.Id,
740 "adapter-status": dh.adapterPreviouslyConnected,
741 "agent-status": dh.agentPreviouslyConnected,
742 })
743 _ = dh.RebootDevice(ctx, dh.device)
744 }
745
Girish Gowdru0c588b22019-04-23 23:24:56 -0400746 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530747}
748
749// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530750func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000751 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400752
khenaidoo106c61a2021-08-11 18:05:46 -0400753 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400754 if err != nil || device == nil {
755 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000756 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400757 }
758
759 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400760
761 //Update the device oper state and connection status
762 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800763 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400764 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800765 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400766
khenaidoodc2116e2021-10-19 17:33:19 -0400767 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400768 DeviceId: cloned.Id,
769 OperStatus: cloned.OperStatus,
770 ConnStatus: cloned.ConnectStatus,
771 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000772 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400773 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400774
775 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400776 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400777 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000778 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400779 }
780 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400781 // Update onu state as down in onu adapter
782 onuInd := oop.OnuIndication{}
783 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400784
785 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
786 if err != nil {
787 return err
788 }
789 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400790 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400791 DeviceId: onuDevice.Id,
792 OnuIndication: &onuInd,
793 })
794 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800795 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400796 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400797 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800798 "onu-indicator": onuInd,
799 "device-type": onuDevice.Type,
800 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700801 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800802 } else {
803 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 -0700804 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400805 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800806 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700807 /* Discovered ONUs entries need to be cleared , since after OLT
808 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530809 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800810 dh.lockDevice.Unlock()
811
Neha Sharma96b7bf22020-06-15 10:37:32 +0000812 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700813 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530814}
815
816// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530817func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400818 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000819
820 // if the connection is already available, close the previous connection (olt reboot case)
821 if dh.clientCon != nil {
822 if err = dh.clientCon.Close(); err != nil {
823 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
824 } else {
825 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
826 }
827 }
828
829 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000830 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
831 grpc.WithInsecure(),
832 grpc.WithBlock(),
833 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000834 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000835 )),
836 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000837 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000838 )))
839
840 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530841 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530842 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000843 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400844 }
845 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530846}
847
848// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530849func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400850 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530851 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400852 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530853}
854
855// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530856func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530857 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000858 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400859
860 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400861 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530862 if err != nil || device == nil {
863 /*TODO: needs to handle error scenarios */
864 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
865 }
866 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000867 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400868
869 cloned := proto.Clone(device).(*voltha.Device)
870 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
871 cloned.OperStatus = voltha.OperStatus_UNKNOWN
872 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400873
khenaidoodc2116e2021-10-19 17:33:19 -0400874 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400875 DeviceId: cloned.Id,
876 OperStatus: cloned.OperStatus,
877 ConnStatus: cloned.ConnectStatus,
878 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530879 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 -0400880 }
881
Chaitrashree G S44124192019-08-07 20:21:36 -0400882 // 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 +0530883 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400884 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530885 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400886 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400887 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
888 // all the modules initialized and ready to handle incoming ONUs.
889
Thomas Lee S985938d2020-05-04 11:40:41 +0530890 err = dh.initializeDeviceHandlerModules(ctx)
891 if err != nil {
892 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 -0400893 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400894
895 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800896 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530897 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400898 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800899 }
900 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700901
902 go startHeartbeatCheck(ctx, dh)
903
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400904 return nil
905 }
906
khenaidoo106c61a2021-08-11 18:05:46 -0400907 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400908 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400909 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400910 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400911 }
khenaidoo106c61a2021-08-11 18:05:46 -0400912 dh.populateActivePorts(ctx, ports.Items)
913 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400914 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400915 }
916
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400917 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530918 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 -0400919 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530920
cuilin20187b2a8c32019-03-26 19:52:28 -0700921 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800922 go func() {
923 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400924 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800925 }
926 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000927 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000928
929 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000930 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000931 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700932
933 go startHeartbeatCheck(ctx, dh)
934
cuilin20187b2a8c32019-03-26 19:52:28 -0700935 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530936}
937
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400938func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700939 var err error
940 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400941
942 if err != nil {
943 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
944 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700945 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
946 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +0000947 // +1 is for NNI
948 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
949 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700950 var i uint32
yasin saplid0566272021-12-21 09:10:30 +0000951 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
952 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
953 // There is only one NNI manager since multiple NNI is not supported for now
954 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700955 // Instantiate resource manager
956 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 -0700957 return olterrors.ErrResourceManagerInstantiating
958 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400959 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700960 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
961 // the KV store to manage mcast group data. Provide the first instance (0th index)
962 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
963 return olterrors.ErrGroupManagerInstantiating
964 }
yasin saplid0566272021-12-21 09:10:30 +0000965 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700966 // Instantiate flow manager
967 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
968 return olterrors.ErrFlowManagerInstantiating
969 }
Girish Gowdra76a1b092021-07-28 10:07:04 -0700970 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700971 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400972 /* TODO: Instantiate Alarm , stats , BW managers */
973 /* Instantiating Event Manager to handle Alarms and KPIs */
974 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
975
976 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000977 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400978
979 return nil
980
981}
982
Neha Sharma96b7bf22020-06-15 10:37:32 +0000983func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400984 var err error
985 var deviceInfo *oop.DeviceInfo
986
Neha Sharma8f4e4322020-08-06 10:51:53 +0000987 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400988
989 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000990 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400991 }
992 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000993 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400994 }
995
Neha Sharma96b7bf22020-06-15 10:37:32 +0000996 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400997 dh.device.Root = true
998 dh.device.Vendor = deviceInfo.Vendor
999 dh.device.Model = deviceInfo.Model
1000 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1001 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1002 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1003
1004 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001005 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001006 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001007 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001008 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001009 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001010 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001011 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001012 dh.device.MacAddress = genmac
1013 } else {
1014 dh.device.MacAddress = deviceInfo.DeviceId
1015 }
1016
1017 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001018 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001019 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001020 }
1021
1022 return deviceInfo, nil
1023}
1024
Neha Sharma96b7bf22020-06-15 10:37:32 +00001025func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001026 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301027 for {
1028 select {
1029 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001030 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301031 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001032 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001033
khenaidoo106c61a2021-08-11 18:05:46 -04001034 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001035 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001036 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001037 continue
1038 }
khenaidoo106c61a2021-08-11 18:05:46 -04001039 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301040 // NNI Stats
1041 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001042 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301043 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001044 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001045 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001046 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301047 }
1048 // PON Stats
1049 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001050 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301051 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1052 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001053 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001054 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301055 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001056 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001057
yasin sapli9e4c5092022-02-01 13:52:33 +00001058 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001059 if len(onuGemInfoLst) > 0 {
1060 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001061 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001062 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301063 }
1064 }
1065 }
1066}
1067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001068//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301069func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001070 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001071 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301072 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301073
1074 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001075 cgClient, err := dh.coreClient.GetCoreServiceClient()
1076 if err != nil {
1077 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1078 return
1079 }
1080
1081 // Now, set the initial PM configuration for that device
1082 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001083 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301084 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301085}
1086
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001087//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001088func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1089 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001090 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301091 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001092 HwDesc: "open_pon",
1093 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001094 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001095 },
1096 SwitchFeatures: &of.OfpSwitchFeatures{
1097 NBuffers: 256,
1098 NTables: 2,
1099 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1100 of.OfpCapabilities_OFPC_TABLE_STATS |
1101 of.OfpCapabilities_OFPC_PORT_STATS |
1102 of.OfpCapabilities_OFPC_GROUP_STATS),
1103 },
1104 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301105}
1106
khenaidoo106c61a2021-08-11 18:05:46 -04001107// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001108func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001109 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001110 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001111 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001112 }
khenaidoo106c61a2021-08-11 18:05:46 -04001113 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001114}
1115
Neha Sharma96b7bf22020-06-15 10:37:32 +00001116func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001117 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 -07001118 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001119 var deviceID string
1120 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001121 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001122
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001123 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001124 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001125 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 -07001126 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1127 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001128
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001129 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301130
1131 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1132
Neha Sharma96b7bf22020-06-15 10:37:32 +00001133 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 -07001134 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001135
khenaidoodc2116e2021-10-19 17:33:19 -04001136 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001137 ParentId: dh.device.Id,
1138 OnuId: omciInd.OnuId,
1139 ParentPortNo: ponPort,
1140 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001141 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301142 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001143 "intf-id": omciInd.IntfId,
1144 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001145 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001146 deviceType = onuDevice.Type
1147 deviceID = onuDevice.Id
1148 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001149 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001150 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001151 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001152 } else {
1153 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001154 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 +05301155 deviceType = onuInCache.(*OnuDevice).deviceType
1156 deviceID = onuInCache.(*OnuDevice).deviceID
1157 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001158 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001159 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001160
khenaidoodc2116e2021-10-19 17:33:19 -04001161 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001162 ParentDeviceId: proxyDeviceID,
1163 ChildDeviceId: deviceID,
1164 Message: omciInd.Pkt,
1165 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301166 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001167 "source": dh.openOLT.config.AdapterEndpoint,
1168 "device-type": deviceType,
1169 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001171 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001172 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301174}
1175
khenaidoo106c61a2021-08-11 18:05:46 -04001176// //ProcessInterAdapterMessage sends the proxied messages to the target device
1177// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1178// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001179// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001180// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001181// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001182// return dh.handleInterAdapterOmciMsg(ctx, msg)
1183// }
1184// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1185// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001186
kesavandb9f54fd2021-11-25 20:08:04 +05301187// ProxyOmciRequests sends the proxied OMCI message to the target device
1188func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
1189 if omciMsgs.GetProxyAddress() == nil {
1190 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1191 if err != nil {
1192 return olterrors.NewErrNotFound("onu", log.Fields{
1193 "parent-device-id": dh.device.Id,
1194 "child-device-id": omciMsgs.ChildDeviceId}, err)
1195 }
1196 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1197 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1198 return olterrors.NewErrCommunication("send-failed", log.Fields{
1199 "parent-device-id": dh.device.Id,
1200 "child-device-id": omciMsgs.ChildDeviceId}, err)
1201 }
1202 } else {
1203 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1204 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1205 return olterrors.NewErrCommunication("send-failed", log.Fields{
1206 "parent-device-id": dh.device.Id,
1207 "child-device-id": omciMsgs.ChildDeviceId}, err)
1208 }
1209 }
1210 return nil
1211}
1212
1213func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1214 var intfID uint32
1215 var onuID uint32
1216 var connectStatus common.ConnectStatus_Types
1217 if onuDevice != nil {
1218 intfID = onuDevice.ProxyAddress.GetChannelId()
1219 onuID = onuDevice.ProxyAddress.GetOnuId()
1220 connectStatus = onuDevice.ConnectStatus
1221 } else {
1222 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1223 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1224 connectStatus = omciMsgs.GetConnectStatus()
1225 }
1226 if connectStatus != voltha.ConnectStatus_REACHABLE {
1227 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1228
1229 return olterrors.NewErrCommunication("unreachable", log.Fields{
1230 "intf-id": intfID,
1231 "onu-id": onuID}, nil)
1232 }
1233
1234 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1235 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1236
1237 onuSecOmciMsgList := omciMsgs.GetMessages()
1238
1239 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1240
1241 var omciMessage *oop.OmciMsg
1242 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1243 hex.Encode(hexPkt, onuSecOmciMsg)
1244 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1245
1246 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1247 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1248 //https://jira.opencord.org/browse/VOL-4604
1249 transid := extractOmciTransactionID(onuSecOmciMsg)
1250 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1251 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1252
1253 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1254 if err != nil {
1255 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1256 "intf-id": intfID,
1257 "onu-id": onuID,
1258 "message": omciMessage}, err)
1259 }
1260 }
1261 return nil
1262}
1263
khenaidoo106c61a2021-08-11 18:05:46 -04001264// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001265func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001266 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 -07001267
1268 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001269 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001270 if err != nil {
1271 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001272 "parent-device-id": dh.device.Id,
1273 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001274 }
khenaidoo106c61a2021-08-11 18:05:46 -04001275 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1276 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001277 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001278 "parent-device-id": dh.device.Id,
1279 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001280 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001281 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001282 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1283 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001284 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001285 "parent-device-id": dh.device.Id,
1286 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001287 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001288 }
1289 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301290}
1291
khenaidoodc2116e2021-10-19 17:33:19 -04001292func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001293 var intfID uint32
1294 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001295 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001296 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001297 intfID = onuDevice.ProxyAddress.GetChannelId()
1298 onuID = onuDevice.ProxyAddress.GetOnuId()
1299 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001300 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001301 intfID = omciMsg.GetProxyAddress().GetChannelId()
1302 onuID = omciMsg.GetProxyAddress().GetOnuId()
1303 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001304 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001305 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001306 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 -08001307
Thomas Lee S94109f12020-03-03 16:39:29 +05301308 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001309 "intf-id": intfID,
1310 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001311 }
1312
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001313 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1314 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301315 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001316 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001317 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1318 hex.Encode(hexPkt, omciMsg.Message)
1319 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1320
1321 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1322 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1323 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001324 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001325 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001326
Neha Sharma8f4e4322020-08-06 10:51:53 +00001327 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001328 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301329 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001330 "intf-id": intfID,
1331 "onu-id": onuID,
1332 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001333 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001334 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001335}
1336
David K. Bainbridge794735f2020-02-11 21:01:37 -08001337func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301338 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 sapli9e4c5092022-02-01 13:52:33 +00001339 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001340 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001341 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001342 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301343 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301344 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001345 st, _ := status.FromError(err)
1346 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001347 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1348
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001349 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301350 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001351 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001352 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001353 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001354 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001355 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001356}
1357
Mahir Gunyelb0046752021-02-26 13:51:05 -08001358func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001359 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001360 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001361
Mahir Gunyelb0046752021-02-26 13:51:05 -08001362 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001363 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301364
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301365 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001366 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001367 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301368
1369 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1370 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1371 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1372 OnuLosRaise event sent for it */
1373 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1374 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1375 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001376 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301377 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1378 "currentIntfId": onuDiscInd.GetIntfId()})
1379 // TODO:: Should we need to ignore raising OnuLosClear event
1380 // when onu connected to different PON?
1381 }
1382 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1383 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1384 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001385 go func() {
1386 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001387 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001388 }
1389 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301390 }
1391 return true
1392 })
1393
Neha Sharma96b7bf22020-06-15 10:37:32 +00001394 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001395 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001396 }
1397
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001398 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001399
1400 // check the ONU is already know to the OLT
1401 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001402 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001403 ParentId: dh.device.Id,
1404 SerialNumber: sn,
1405 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001406
1407 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001408 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 -08001409 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001410 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 -08001411 switch e.Code() {
1412 case codes.Internal:
1413 // this probably means NOT FOUND, so just create a new device
1414 onuDevice = nil
1415 case codes.DeadlineExceeded:
1416 // if the call times out, cleanup and exit
1417 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001418 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001419 }
1420 }
1421 }
1422
1423 if onuDevice == nil {
1424 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001425 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001426 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001427 ponintfid := onuDiscInd.GetIntfId()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001428 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001429
Neha Sharma96b7bf22020-06-15 10:37:32 +00001430 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001431
1432 if err != nil {
1433 // if we can't create an ID in resource manager,
1434 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001435 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001436 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001437 "pon-intf-id": ponintfid,
1438 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001439 }
1440
khenaidoodc2116e2021-10-19 17:33:19 -04001441 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001442 ParentId: dh.device.Id,
1443 ParentPortNo: parentPortNo,
1444 ChannelId: channelID,
1445 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1446 SerialNumber: sn,
1447 OnuId: onuID,
1448 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001449 dh.discOnus.Delete(sn)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001450 dh.resourceMgr[ponintfid].FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301451 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001452 "pon-intf-id": ponintfid,
1453 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001454 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001455 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 -07001456 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001457 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001458 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301459 log.Fields{"onuDevice": onuDevice,
1460 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001461 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301462 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001463 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001464
khenaidoo106c61a2021-08-11 18:05:46 -04001465 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1466 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1467 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1468 cancel()
1469 if err != nil {
1470 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1471 }
1472
Matteo Scandolo945e4012019-12-12 14:16:11 -08001473 // we can now use the existing ONU Id
1474 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001475 //Insert the ONU into cache to use in OnuIndication.
1476 //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 +00001477 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001478 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301479 "intfId": onuDiscInd.GetIntfId(),
1480 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001481 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001482
khenaidoo106c61a2021-08-11 18:05:46 -04001483 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301484 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001485 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301486 log.Fields{"onu": onuDev,
1487 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001488
khenaidoodc2116e2021-10-19 17:33:19 -04001489 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001490 DeviceId: onuDevice.Id,
1491 ParentDeviceId: dh.device.Id,
1492 OperStatus: common.OperStatus_DISCOVERED,
1493 ConnStatus: common.ConnectStatus_REACHABLE,
1494 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301495 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001496 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001497 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001498 }
khenaidoo106c61a2021-08-11 18:05:46 -04001499
Neha Sharma96b7bf22020-06-15 10:37:32 +00001500 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001501 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301502 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001503 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001504 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001505 }
1506 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001507}
1508
Mahir Gunyelb0046752021-02-26 13:51:05 -08001509func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001510
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001511 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001512 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001513 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001514 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001515 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301516 log.Fields{"onuId": onuInd.OnuId,
1517 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301518 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001519 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001520 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301521
David K. Bainbridge794735f2020-02-11 21:01:37 -08001522 errFields := log.Fields{"device-id": dh.device.Id}
1523
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301524 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1525
Mahir Gunyele77977b2019-06-27 05:36:22 -07001526 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1527 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001528 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001529 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001530 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001531 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1532 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001533 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001534 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001535 errFields["onu-id"] = onuInd.OnuId
1536 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001537 }
khenaidoodc2116e2021-10-19 17:33:19 -04001538 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001539 ParentId: dh.device.Id,
1540 SerialNumber: serialNumber,
1541 OnuId: onuInd.OnuId,
1542 ParentPortNo: ponPort,
1543 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001544 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001545
David K. Bainbridge794735f2020-02-11 21:01:37 -08001546 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001547 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001548 }
1549
David K. Bainbridge794735f2020-02-11 21:01:37 -08001550 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001551 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001552 "previousIntfId": onuDevice.ParentPortNo,
1553 "currentIntfId": ponPort})
1554 }
1555
1556 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001557 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301558 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1559 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301560 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001561 }
1562 if !foundInCache {
1563 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1564
khenaidoo106c61a2021-08-11 18:05:46 -04001565 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 -08001566
1567 }
kesavand7cf3a052020-08-28 12:49:18 +05301568 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001569 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001570 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301571 }
1572 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001573 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001574 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001575 }
1576 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001577}
1578
Neha Sharma96b7bf22020-06-15 10:37:32 +00001579func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001580 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 -07001581 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1582 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1583 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1584 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001585 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001586 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1587 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001588 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001589 onuInd.OperState = "down"
1590 }
1591 }
1592
David K. Bainbridge794735f2020-02-11 21:01:37 -08001593 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001594 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001595 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 -04001596
khenaidoodc2116e2021-10-19 17:33:19 -04001597 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001598 DeviceId: onuDevice.Id,
1599 OnuIndication: onuInd,
1600 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001601 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301602 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001603 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001604 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001606 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001607 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001608 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001609 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001610 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001611 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001612}
1613
cuilin20187b2a8c32019-03-26 19:52:28 -07001614func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1615 if serialNum != nil {
1616 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001617 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001618 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001619}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001620func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1621 decodedStr, err := hex.DecodeString(serialNum[4:])
1622 if err != nil {
1623 return nil, err
1624 }
1625 return &oop.SerialNumber{
1626 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001627 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001628 }, nil
1629}
cuilin20187b2a8c32019-03-26 19:52:28 -07001630
1631func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001632 if len(vendorSpecific) > 3 {
1633 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1634 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1635 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1636 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1637 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1638 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1639 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1640 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1641 return tmp
1642 }
1643 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001644}
1645
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001646//UpdateFlowsBulk upates the bulk flow
1647func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301648 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001649}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001650
1651//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001652func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1653 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301654 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001655 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301656 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001657
khenaidoodc2116e2021-10-19 17:33:19 -04001658 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001659 ParentId: dh.device.Id,
1660 OnuId: onuID,
1661 ParentPortNo: parentPort,
1662 })
1663
Girish Gowdru0c588b22019-04-23 23:24:56 -04001664 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001665 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001666 "intf-id": parentPort,
1667 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001668 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669 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 -08001670 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301671}
1672
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001673// SendPacketInToCore sends packet-in to core
1674// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1675// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001676func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001677 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001678 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001679 "port": logicalPort,
1680 "packet": hex.EncodeToString(packetPayload),
1681 "device-id": dh.device.Id,
1682 })
1683 }
khenaidoo106c61a2021-08-11 18:05:46 -04001684
khenaidoodc2116e2021-10-19 17:33:19 -04001685 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001686 DeviceId: dh.device.Id,
1687 Port: logicalPort,
1688 Packet: packetPayload,
1689 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301690 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001691 "source": "adapter",
1692 "destination": "core",
1693 "device-id": dh.device.Id,
1694 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001695 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001696 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001697 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001698 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001699 "packet": hex.EncodeToString(packetPayload),
1700 "device-id": dh.device.Id,
1701 })
1702 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001703 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001704}
1705
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001706// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001707func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001708 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001709
1710 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1711 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001712 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001713 }
1714
Kent Hagermane6ff1012020-07-14 15:07:53 -04001715 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001716 metrics := dh.metrics.GetSubscriberMetrics()
1717 for _, m := range pmConfigs.Metrics {
1718 metrics[m.Name].Enabled = m.Enabled
1719
1720 }
1721 }
1722}
1723
khenaidoodc2116e2021-10-19 17:33:19 -04001724func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001725 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001726 var errorsList []error
1727
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001728 if dh.getDeviceDeletionInProgressFlag() {
1729 // The device itself is going to be reset as part of deletion. So nothing to be done.
1730 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1731 return nil
1732 }
1733
Girish Gowdru0c588b22019-04-23 23:24:56 -04001734 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001735 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001736 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001737
Neha Sharma96b7bf22020-06-15 10:37:32 +00001738 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301739 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001740 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301741 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001742 if flow_utils.HasGroup(flow) {
1743 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1744 } else {
yasin saplid0566272021-12-21 09:10:30 +00001745 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
Girish Gowdra491a9c62021-01-06 16:43:07 -08001746 }
Girish Gowdracefae192020-03-19 18:14:10 -07001747 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01001748 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
1749 //The flow we want to remove is not there, there is no need to throw an error
1750 logger.Warnw(ctx, "flow-to-remove-not-found",
1751 log.Fields{
1752 "ponIf": intfID,
1753 "flowToRemove": flow,
1754 "error": err,
1755 })
1756 } else {
1757 errorsList = append(errorsList, err)
1758 }
Girish Gowdracefae192020-03-19 18:14:10 -07001759 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001760 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301761
1762 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00001763 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001764 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301765 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001766 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301767 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001768 if flow_utils.HasGroup(flow) {
1769 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1770 } else {
yasin saplid0566272021-12-21 09:10:30 +00001771 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001772 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1773 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1774 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1775 } else {
yasin saplid0566272021-12-21 09:10:30 +00001776 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001777 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001778 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001779 if err != nil {
1780 errorsList = append(errorsList, err)
1781 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301782 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001783 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001784
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001785 return errorsList
1786}
1787
1788func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1789 var err error
1790 var errorsList []error
1791
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001792 if dh.getDeviceDeletionInProgressFlag() {
1793 // The device itself is going to be reset as part of deletion. So nothing to be done.
1794 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1795 return nil
1796 }
1797
Girish Gowdracefae192020-03-19 18:14:10 -07001798 // 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 +00001799 if groups != nil {
1800 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001801 // err = dh.groupMgr.AddGroup(ctx, group)
1802 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001803 if err != nil {
1804 errorsList = append(errorsList, err)
1805 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001806 }
1807 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001808 // err = dh.groupMgr.ModifyGroup(ctx, group)
1809 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001810 if err != nil {
1811 errorsList = append(errorsList, err)
1812 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001813 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001814 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001815 // err = dh.groupMgr.DeleteGroup(ctx, group)
1816 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001817 if err != nil {
1818 errorsList = append(errorsList, err)
1819 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001820 }
1821 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001822
1823 return errorsList
1824}
1825
1826//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001827func (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 -07001828
1829 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001830
1831 if dh.getDeviceDeletionInProgressFlag() {
1832 // The device itself is going to be reset as part of deletion. So nothing to be done.
1833 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1834 return nil
1835 }
1836
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001837 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1838 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1839 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001840 if len(errorsList) > 0 {
1841 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1842 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001843 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001844 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301845}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001846
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001847//DisableDevice disables the given device
1848//It marks the following for the given device:
1849//Device-Handler Admin-State : down
1850//Device Port-State: UNKNOWN
1851//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001852func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001853 /* On device disable ,admin state update has to be done prior sending request to agent since
1854 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001855 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001856 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001857 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001858 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001859 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001860 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001861 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001862 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001863 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001864 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301865
1866 dh.discOnus = sync.Map{}
1867 dh.onus = sync.Map{}
1868
Thomas Lee S85f37312020-04-03 17:06:12 +05301869 //stopping the stats collector
1870 dh.stopCollector <- true
1871
Neha Sharma96b7bf22020-06-15 10:37:32 +00001872 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001873 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301874 //Update device Admin state
1875 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001876
kdarapu1afeceb2020-02-12 01:38:09 -05001877 // 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 -04001878 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001879 DeviceId: cloned.Id,
1880 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
1881 OperStatus: voltha.OperStatus_UNKNOWN,
1882 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001883 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001884 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001885 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001886 return nil
1887}
1888
Neha Sharma96b7bf22020-06-15 10:37:32 +00001889func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001890 // Update onu state as unreachable in onu adapter
1891 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301892 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04001893
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001894 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001895 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001896 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001897 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 -04001898 }
1899 if onuDevices != nil {
1900 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04001901 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001902 DeviceId: onuDevice.Id,
1903 OnuIndication: &onuInd,
1904 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001905 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001906 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001907 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001908 }
1909
1910 }
1911 }
1912
1913}
1914
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001915//ReenableDevice re-enables the olt device after disable
1916//It marks the following for the given device:
1917//Device-Handler Admin-State : up
1918//Device Port-State: ACTIVE
1919//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001920func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001921 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301922 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001923 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301924 }
1925 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001926 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001927
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001928 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04001929 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001930 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001931 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001932 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
1933 } else {
1934 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1935 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
1936 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001937 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001938 if retError == nil {
1939 //Update the device oper status as ACTIVE
1940 device.OperStatus = voltha.OperStatus_ACTIVE
1941 } else {
1942 //Update the device oper status as FAILED
1943 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001944 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001945 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001946
khenaidoodc2116e2021-10-19 17:33:19 -04001947 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001948 DeviceId: device.Id,
1949 OperStatus: device.OperStatus,
1950 ConnStatus: device.ConnectStatus,
1951 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301952 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001953 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001954 "connect-status": device.ConnectStatus,
1955 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001956 }
kesavand39e0aa32020-01-28 20:58:50 -05001957
Neha Sharma96b7bf22020-06-15 10:37:32 +00001958 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001959
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001960 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001961}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001962
npujarec5762e2020-01-01 14:08:48 +05301963func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001964 var uniID uint32
1965 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301966 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001967 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001968 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001969 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001970 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001971 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001972 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001973 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001974 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001975 for _, tpID := range tpIDList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001976 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001977 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001978 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001979 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001980 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001981 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001982 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001983 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301984 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001985 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1986 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001987 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301988 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001989 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001990 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001991 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 +00001992 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001993 }
1994 return nil
1995}
1996
Devmalya Paul495b94a2019-08-27 19:42:00 -04001997// 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 +05301998func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001999 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002000 /* Clear the KV store data associated with the all the UNI ports
2001 This clears up flow data and also resource map data for various
2002 other pon resources like alloc_id and gemport_id
2003 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002004
2005 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002006 var wg sync.WaitGroup
2007 wg.Add(1) // for the mcast routine below to finish
2008 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2009 for _, flMgr := range dh.flowMgr {
2010 wg.Add(1) // for the flow handler routine below to finish
2011 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2012 }
2013 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2014 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2015 } else {
2016 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2017 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002018
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002019 dh.cleanupDeviceResources(ctx)
2020 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 -04002021 // Stop the Stats collector
2022 dh.stopCollector <- true
2023 // stop the heartbeat check routine
2024 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05302025 dh.lockDevice.RLock()
2026 // Stop the read indication only if it the routine is active
2027 if dh.isReadIndicationRoutineActive {
2028 dh.stopIndications <- true
2029 }
2030 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002031 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002032 //Reset the state
2033 if dh.Client != nil {
2034 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302035 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002036 }
2037 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002038 // There is no need to update the core about operation status and connection status of the OLT.
2039 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2040 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2041 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002042
khenaidoo7eb2d672021-10-22 19:08:50 -04002043 // Stop the adapter grpc clients for that parent device
2044 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002045 return nil
2046}
Kent Hagermane6ff1012020-07-14 15:07:53 -04002047func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002048
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002049 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302050 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002051 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002052 var err error
yasin sapli9e4c5092022-02-01 13:52:33 +00002053 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002054 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002055 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002056 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002057 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302058 }
2059 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002060 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx, ponPort)
2061 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx, ponPort)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002062 dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002063 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2064 logger.Debug(ctx, err)
2065 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002066 }
yasin saplid0566272021-12-21 09:10:30 +00002067 _ = dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx, dh.totalPonPorts)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002068 }
A R Karthick1f85b802019-10-11 05:06:05 +00002069
Devmalya Paul495b94a2019-08-27 19:42:00 -04002070 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302071 dh.onus.Range(func(key interface{}, value interface{}) bool {
2072 dh.onus.Delete(key)
2073 return true
2074 })
2075
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002076 /*Delete discovered ONU map for the device*/
2077 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2078 dh.discOnus.Delete(key)
2079 return true
2080 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002081}
2082
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002083//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002084func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002085 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302086 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002087 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002088 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002089 return nil
2090}
2091
David K. Bainbridge794735f2020-02-11 21:01:37 -08002092func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002093 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002094 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002095 "packet-indication": *packetIn,
2096 "device-id": dh.device.Id,
2097 "packet": hex.EncodeToString(packetIn.Pkt),
2098 })
2099 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002100 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002101 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002102 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002103 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002104 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002105 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002106 "logical-port-num": logicalPortNum,
2107 "device-id": dh.device.Id,
2108 "packet": hex.EncodeToString(packetIn.Pkt),
2109 })
2110 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002111
khenaidoodc2116e2021-10-19 17:33:19 -04002112 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002113 DeviceId: dh.device.Id,
2114 Port: logicalPortNum,
2115 Packet: packetIn.Pkt,
2116 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302117 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002118 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302119 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002120 "device-id": dh.device.Id,
2121 "packet": hex.EncodeToString(packetIn.Pkt),
2122 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002123 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002124
Matteo Scandolo92186242020-06-12 10:54:18 -07002125 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002126 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002127 "packet": hex.EncodeToString(packetIn.Pkt),
2128 "device-id": dh.device.Id,
2129 })
2130 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002131 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002132}
2133
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002134// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002135func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002136 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002137 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002138 "device-id": dh.device.Id,
2139 "egress-port-no": egressPortNo,
2140 "pkt-length": len(packet.Data),
2141 "packet": hex.EncodeToString(packet.Data),
2142 })
2143 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002144
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002145 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002146 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002147 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2148 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302149 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2150 // Do not packet-out lldp packets on uni port.
2151 // ONOS has no clue about uni/nni ports, it just packets out on all
2152 // available ports on the Logical Switch. It should not be interested
2153 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002154 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002155 "device-id": dh.device.Id,
2156 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302157 return nil
2158 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002159 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2160 if innerEthType == 0x8100 {
2161 // q-in-q 802.1ad or 802.1q double tagged packet.
2162 // slice out the outer tag.
2163 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002164 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002165 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002166 "packet-data": hex.EncodeToString(packet.Data),
2167 "device-id": dh.device.Id,
2168 })
2169 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002170 }
2171 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002172 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2173 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2174 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002175
Girish Gowdra9602eb42020-09-09 15:50:39 -07002176 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002177 if err != nil {
2178 // In this case the openolt agent will receive the gemPortID as 0.
2179 // The agent tries to retrieve the gemPortID in this case.
2180 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002181 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002182 "intf-id": intfID,
2183 "onu-id": onuID,
2184 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002185 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302186 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002187 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002188 }
2189
2190 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002191 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002192 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002193 "egress-port-no": egressPortNo,
2194 "intf-id": intfID,
2195 "onu-id": onuID,
2196 "uni-id": uniID,
2197 "gem-port-id": gemPortID,
2198 "packet": hex.EncodeToString(packet.Data),
2199 "device-id": dh.device.Id,
2200 })
2201 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002202
npujarec5762e2020-01-01 14:08:48 +05302203 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302204 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002205 "source": "adapter",
2206 "destination": "onu",
2207 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002208 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002209 "oni-id": onuID,
2210 "uni-id": uniID,
2211 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002212 "packet": hex.EncodeToString(packet.Data),
2213 "device-id": dh.device.Id,
2214 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002215 }
2216 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002217 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002218 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002219 return olterrors.NewErrInvalidValue(log.Fields{
2220 "egress-nni-port": egressPortNo,
2221 "device-id": dh.device.Id,
2222 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002223 }
2224 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002225
Matteo Scandolo92186242020-06-12 10:54:18 -07002226 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002227 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002228 "uplink-pkt": uplinkPkt,
2229 "packet": hex.EncodeToString(packet.Data),
2230 "device-id": dh.device.Id,
2231 })
2232 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002233
npujarec5762e2020-01-01 14:08:48 +05302234 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002235 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2236 "packet": hex.EncodeToString(packet.Data),
2237 "device-id": dh.device.Id,
2238 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002239 }
2240 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002241 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302242 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002243 "egressPortType": egressPortType,
2244 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302245 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002246 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002247 }
2248 return nil
2249}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002250
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002251func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2252 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002253}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302254
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002255func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002256
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302257 // start the heartbeat check towards the OLT.
2258 var timerCheck *time.Timer
2259
2260 for {
2261 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2262 select {
2263 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002264 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002265 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002266 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302267 if timerCheck == nil {
2268 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002269 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302270 }
2271 } else {
2272 if timerCheck != nil {
2273 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002274 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302275 }
2276 timerCheck = nil
2277 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002278 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302279 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302280 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302281 }
2282 cancel()
2283 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002284 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302285 return
2286 }
2287 }
2288}
2289
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002290func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002291 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002292 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002293 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2294 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2295 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2296 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2297 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002298 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002299 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2300 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002301 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302302
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002303 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2304 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002305 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002306 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002307 DeviceId: dh.device.Id,
2308 OperStatus: voltha.OperStatus_UNKNOWN,
2309 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2310 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002311 _ = 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 -04002312 }
khenaidoo106c61a2021-08-11 18:05:46 -04002313
khenaidoodc2116e2021-10-19 17:33:19 -04002314 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002315 DeviceId: dh.device.Id,
2316 PortTypeFilter: 0,
2317 OperStatus: voltha.OperStatus_UNKNOWN,
2318 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002319 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002320 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002321
2322 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002323 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002324 cloned := proto.Clone(device).(*voltha.Device)
2325 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2326 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2327 dh.device = cloned // update local copy of the device
2328 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002329
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002330 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002331 // Stop the Stats collector
2332 dh.stopCollector <- true
2333 // stop the heartbeat check routine
2334 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002335
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002336 dh.lockDevice.RLock()
2337 // Stop the read indication only if it the routine is active
2338 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2339 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2340 // on next execution of the readIndication routine.
2341 if dh.isReadIndicationRoutineActive {
2342 dh.stopIndications <- true
2343 }
2344 dh.lockDevice.RUnlock()
2345
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002346 var wg sync.WaitGroup
2347 wg.Add(1) // for the multicast handler routine
2348 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002349 for _, flMgr := range dh.flowMgr {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002350 wg.Add(1) // for the flow handler routine
2351 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2352 }
2353 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2354 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2355 } else {
2356 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002357 }
2358
Gamze Abakac2c32a62021-03-11 11:44:18 +00002359 //reset adapter reconcile flag
2360 dh.adapterPreviouslyConnected = false
2361
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002362 dh.transitionMap.Handle(ctx, DeviceInit)
2363
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302364 }
2365}
kesavand39e0aa32020-01-28 20:58:50 -05002366
2367// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002368func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2369 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2370 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002371}
2372
2373// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002374func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2375 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2376 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002377}
2378
kdarapu1afeceb2020-02-12 01:38:09 -05002379//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 +00002380func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2381 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002382 if port.GetType() == voltha.Port_ETHERNET_NNI {
2383 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302385 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302386 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002387 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002388 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002389 }
2390 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002391 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002392 ponIntf := &oop.Interface{IntfId: ponID}
2393 var operStatus voltha.OperStatus_Types
2394 if enablePort {
2395 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302396 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002397
2398 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302399 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002400 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002401 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002402 }
2403 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002404 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002405 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002406 } else {
2407 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302408 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002409 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302410 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002411 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002412 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002413 }
2414 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002415 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002416 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002417 }
khenaidoodc2116e2021-10-19 17:33:19 -04002418 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002419 DeviceId: dh.device.Id,
2420 PortType: voltha.Port_PON_OLT,
2421 PortNo: port.PortNo,
2422 OperStatus: operStatus,
2423 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302424 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302425 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002426 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002427 }
2428 return nil
2429}
2430
kdarapu1afeceb2020-02-12 01:38:09 -05002431//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002432func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002433 // Disable the port and update the oper_port_status to core
2434 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002435 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002436 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002437 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302438 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302439 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002440 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002441 }
2442 }
2443 }
2444 return nil
2445}
2446
2447//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002448func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2449 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2450 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002451 if port.Type == voltha.Port_ETHERNET_NNI {
2452 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002453 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002454 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002455 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002456 }
2457 }
2458 if port.Type == voltha.Port_PON_OLT {
2459 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002460 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002461 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002462 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002463 }
2464 }
2465 }
2466}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002467
2468// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002469func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002470 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002471 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002472 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002473
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002474 var sn *oop.SerialNumber
2475 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002476 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302477 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002478 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302479 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002480 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002481 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002482
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002483 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002484 //clear PON resources associated with ONU
2485 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, intfID, onuID)
2486 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2487 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2488 "device-id": dh.device.Id,
2489 "intf-id": intfID,
2490 "onuID": onuID,
2491 "err": err})
2492 } else {
2493 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
2494 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2495 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2496 "device-id": dh.device.Id,
2497 "onu-device": onu,
2498 "err": err})
2499 }
2500 // Clear flowids for gem cache.
2501 for _, gem := range onuGem.GemPorts {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002502 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, intfID, gem)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002503 }
yasin sapli9e4c5092022-02-01 13:52:33 +00002504 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, intfID, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002505 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2506 "intf-id": intfID,
2507 "onu-device": onu,
2508 "onu-gem": onuGem,
2509 "err": err})
2510 //Not returning error on cleanup.
2511 }
2512 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302513
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002514 }
Himani Chawlabcc95852021-10-27 10:55:40 +05302515 dh.resourceMgr[intfID].FreeonuID(ctx, intfID, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002516 dh.onus.Delete(onuKey)
2517 dh.discOnus.Delete(onuSn)
2518
2519 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002520 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302521 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302522 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002523 "onu-id": onuID}, err).Log()
2524 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002525
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002526 return nil
2527}
Girish Gowdracefae192020-03-19 18:14:10 -07002528
2529func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002530 for _, field := range flow_utils.GetOfbFields(flow) {
2531 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002532 return field.GetPort()
2533 }
2534 }
2535 return InvalidPort
2536}
2537
2538func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002539 for _, action := range flow_utils.GetActions(flow) {
2540 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002541 if out := action.GetOutput(); out != nil {
2542 return out.GetPort()
2543 }
2544 }
2545 }
2546 return InvalidPort
2547}
2548
Girish Gowdracefae192020-03-19 18:14:10 -07002549func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2550 inPort := getInPortFromFlow(flow)
2551 outPort := getOutPortFromFlow(flow)
2552
2553 if inPort == InvalidPort || outPort == InvalidPort {
2554 return inPort, outPort
2555 }
2556
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002557 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002558 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002559 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002560 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002561 return uniPort, outPort
2562 }
2563 }
2564 } else {
2565 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002566 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002567 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002568 return inPort, uniPort
2569 }
2570 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002571 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002572 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002573 return uniPort, outPort
2574 }
2575 }
2576 }
2577
2578 return InvalidPort, InvalidPort
2579}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002580
2581func extractOmciTransactionID(omciPkt []byte) uint16 {
2582 if len(omciPkt) > 3 {
2583 d := omciPkt[0:2]
2584 transid := binary.BigEndian.Uint16(d)
2585 return transid
2586 }
2587 return 0
2588}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002589
2590// StoreOnuDevice stores the onu parameters to the local cache.
2591func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2592 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2593 dh.onus.Store(onuKey, onuDevice)
2594}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002595
khenaidoodc2116e2021-10-19 17:33:19 -04002596func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002597 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002598 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002599 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002600 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002601 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002602 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002603 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002604 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2605 return nil, err
2606 }
2607 ID = device.ProxyAddress.GetOnuId()
2608 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2609 valueparam.Onu = &Onu
2610 valueparam.Value = value
2611
2612 // This API is unsupported until agent patch is added
2613 resp.Unsupported = uint32(value)
2614 _ = ctx
2615
2616 // Uncomment this code once agent changes are complete and tests
2617 /*
2618 resp, err = dh.Client.GetValue(ctx, valueparam)
2619 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002620 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002621 return nil, err
2622 }
2623 */
2624
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002625 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 -08002626 return resp, nil
2627}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002628
yasin saplid0566272021-12-21 09:10:30 +00002629func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
2630 // Default to NNI
2631 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07002632 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002633 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002634 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002635 }
2636 return intfID
2637}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002638
Mahir Gunyelb0046752021-02-26 13:51:05 -08002639func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2640 dh.perPonOnuIndicationChannelLock.Lock()
2641 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2642 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002643 return ch.indicationChannel
2644 }
2645 channels := onuIndicationChannels{
2646 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002647 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002648 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002649 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002650 stopChannel: make(chan struct{}),
2651 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002652 dh.perPonOnuIndicationChannel[intfID] = channels
2653 dh.perPonOnuIndicationChannelLock.Unlock()
2654 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002655 return channels.indicationChannel
2656
2657}
2658
Mahir Gunyelb0046752021-02-26 13:51:05 -08002659func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2660 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2661 dh.perPonOnuIndicationChannelLock.Lock()
2662 defer dh.perPonOnuIndicationChannelLock.Unlock()
2663 for _, v := range dh.perPonOnuIndicationChannel {
2664 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002665 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002666 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002667}
2668
Mahir Gunyelb0046752021-02-26 13:51:05 -08002669func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2670 ind := onuIndicationMsg{
2671 ctx: ctx,
2672 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002673 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002674 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002675 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002676 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002677}
2678
Mahir Gunyelb0046752021-02-26 13:51:05 -08002679func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002680 for {
2681 select {
2682 // process one indication per onu, before proceeding to the next one
2683 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08002684 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002685 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08002686 "ind": indication})
2687 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002688 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002689 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002690 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2691 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002692 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002693 }
2694 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002695 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002696 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2697 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002698 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002699 }
2700 }
2701 case <-onuChannels.stopChannel:
2702 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2703 close(onuChannels.indicationChannel)
2704 return
2705 }
2706 }
2707}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002708
2709// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2710// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04002711func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002712 if dh.getDeviceDeletionInProgressFlag() {
2713 // The device itself is going to be reset as part of deletion. So nothing to be done.
2714 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2715 return nil
2716 }
2717
Girish Gowdra491a9c62021-01-06 16:43:07 -08002718 // Step1 : Fill McastFlowOrGroupControlBlock
2719 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2720 // Step3 : Wait on response channel for response
2721 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002722 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002723 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2724 errChan := make(chan error)
2725 var groupID uint32
2726 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2727 ctx: ctx,
2728 flowOrGroupAction: action,
2729 flow: flow,
2730 group: group,
2731 errChan: &errChan,
2732 }
2733 if flow != nil {
2734 groupID = flow_utils.GetGroup(flow)
2735 } else if group != nil {
2736 groupID = group.Desc.GroupId
2737 } else {
2738 return errors.New("flow-and-group-both-nil")
2739 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002740 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2741 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2742 // Derive the appropriate go routine to handle the request by a simple module operation.
2743 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2744 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2745 // Wait for handler to return error value
2746 err := <-errChan
2747 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2748 return err
2749 }
2750 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2751 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002752}
2753
2754// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002755func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002756 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002757 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002758 // block on the channel to receive an incoming mcast flow/group
2759 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002760 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2761 if mcastFlowOrGroupCb.flow != nil {
2762 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2763 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2764 log.Fields{"device-id": dh.device.Id,
2765 "flowToAdd": mcastFlowOrGroupCb.flow})
2766 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2767 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2768 // Pass the return value over the return channel
2769 *mcastFlowOrGroupCb.errChan <- err
2770 } else { // flow remove
2771 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2772 log.Fields{"device-id": dh.device.Id,
2773 "flowToRemove": mcastFlowOrGroupCb.flow})
2774 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2775 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2776 // Pass the return value over the return channel
2777 *mcastFlowOrGroupCb.errChan <- err
2778 }
2779 } else { // mcast group
2780 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2781 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2782 log.Fields{"device-id": dh.device.Id,
2783 "groupToAdd": mcastFlowOrGroupCb.group})
2784 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2785 // Pass the return value over the return channel
2786 *mcastFlowOrGroupCb.errChan <- err
2787 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2788 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2789 log.Fields{"device-id": dh.device.Id,
2790 "groupToModify": mcastFlowOrGroupCb.group})
2791 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2792 // Pass the return value over the return channel
2793 *mcastFlowOrGroupCb.errChan <- err
2794 } else { // group remove
2795 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2796 log.Fields{"device-id": dh.device.Id,
2797 "groupToRemove": mcastFlowOrGroupCb.group})
2798 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2799 // Pass the return value over the return channel
2800 *mcastFlowOrGroupCb.errChan <- err
2801 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002802 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002803 case <-stopHandler:
2804 dh.mcastHandlerRoutineActive[routineIndex] = false
2805 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08002806 }
2807 }
2808}
kesavand62126212021-01-12 04:56:06 -05002809
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002810// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002811func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002812 for i, v := range dh.stopMcastHandlerRoutine {
2813 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002814 select {
2815 case v <- true:
2816 case <-time.After(time.Second * 5):
2817 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
2818 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002819 }
2820 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002821 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002822 logger.Debug(ctx, "stopped all mcast handler routines")
2823}
2824
kesavand62126212021-01-12 04:56:06 -05002825func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2826
2827 singleValResp := extension.SingleGetValueResponse{
2828 Response: &extension.GetValueResponse{
2829 Response: &extension.GetValueResponse_PortCoutners{
2830 PortCoutners: &extension.GetOltPortCountersResponse{},
2831 },
2832 },
2833 }
2834
2835 errResp := func(status extension.GetValueResponse_Status,
2836 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2837 return &extension.SingleGetValueResponse{
2838 Response: &extension.GetValueResponse{
2839 Status: status,
2840 ErrReason: reason,
2841 },
2842 }
2843 }
2844
2845 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2846 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2847 //send error response
2848 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2849 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2850 }
2851 statIndChn := make(chan bool, 1)
2852 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2853 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2854 //request openOlt agent to send the the port statistics indication
2855
2856 go func() {
2857 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2858 if err != nil {
2859 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2860 }
2861 }()
2862 select {
2863 case <-statIndChn:
2864 //indication received for ports stats
2865 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2866 case <-time.After(oltPortInfoTimeout * time.Second):
2867 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2868 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2869 case <-ctx.Done():
2870 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2871 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2872 }
2873 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2874 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002875 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05002876 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2877 cmnni := dh.portStats.collectNNIMetrics(intfID)
2878 if cmnni == nil {
2879 //TODO define the error reason
2880 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2881 }
2882 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2883 return &singleValResp
2884
2885 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2886 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002887 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05002888 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2889 cmpon := dh.portStats.collectPONMetrics(intfID)
2890 if cmpon == nil {
2891 //TODO define the error reason
2892 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2893 }
2894 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2895 return &singleValResp
2896 }
2897 }
2898 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2899}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302900
2901func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2902
2903 singleValResp := extension.SingleGetValueResponse{
2904 Response: &extension.GetValueResponse{
2905 Response: &extension.GetValueResponse_OnuPonCounters{
2906 OnuPonCounters: &extension.GetOnuCountersResponse{},
2907 },
2908 },
2909 }
2910
2911 errResp := func(status extension.GetValueResponse_Status,
2912 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2913 return &extension.SingleGetValueResponse{
2914 Response: &extension.GetValueResponse{
2915 Status: status,
2916 ErrReason: reason,
2917 },
2918 }
2919 }
2920 intfID := onuPonInfo.IntfId
2921 onuID := onuPonInfo.OnuId
2922 onuKey := dh.formOnuKey(intfID, onuID)
2923
2924 if _, ok := dh.onus.Load(onuKey); !ok {
2925 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2926 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2927 }
2928 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2929 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2930 if cmnni == nil {
2931 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2932 }
2933 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2934 return &singleValResp
2935
2936}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002937
2938func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2939
2940 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
2941 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
2942 if err != nil {
2943 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
2944 return generateSingleGetValueErrorResponse(err)
2945 }
2946 return &extension.SingleGetValueResponse{
2947 Response: &extension.GetValueResponse{
2948 Status: extension.GetValueResponse_OK,
2949 Response: &extension.GetValueResponse_RxPower{
2950 RxPower: &extension.GetRxPowerResponse{
2951 IntfId: rxPowerRequest.IntfId,
2952 OnuId: rxPowerRequest.OnuId,
2953 Status: rxPower.Status,
2954 FailReason: rxPower.FailReason.String(),
2955 RxPower: rxPower.RxPowerMeanDbm,
2956 },
2957 },
2958 },
2959 }
2960}
2961
2962func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
2963 errResp := func(status extension.GetValueResponse_Status,
2964 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2965 return &extension.SingleGetValueResponse{
2966 Response: &extension.GetValueResponse{
2967 Status: status,
2968 ErrReason: reason,
2969 },
2970 }
2971 }
2972
2973 if err != nil {
2974 if e, ok := status.FromError(err); ok {
2975 switch e.Code() {
2976 case codes.Internal:
2977 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2978 case codes.DeadlineExceeded:
2979 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2980 case codes.Unimplemented:
2981 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
2982 case codes.NotFound:
2983 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2984 }
2985 }
2986 }
2987
2988 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
2989}
khenaidoo106c61a2021-08-11 18:05:46 -04002990
2991/*
2992Helper functions to communicate with Core
2993*/
2994
2995func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
2996 cClient, err := dh.coreClient.GetCoreServiceClient()
2997 if err != nil || cClient == nil {
2998 return nil, err
2999 }
3000 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3001 defer cancel()
3002 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3003}
3004
khenaidoodc2116e2021-10-19 17:33:19 -04003005func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003006 cClient, err := dh.coreClient.GetCoreServiceClient()
3007 if err != nil || cClient == nil {
3008 return nil, err
3009 }
3010 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3011 defer cancel()
3012 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3013}
3014
khenaidoodc2116e2021-10-19 17:33:19 -04003015func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003016 cClient, err := dh.coreClient.GetCoreServiceClient()
3017 if err != nil || cClient == nil {
3018 return err
3019 }
3020 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3021 defer cancel()
3022 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3023 return err
3024}
3025
3026func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3027 cClient, err := dh.coreClient.GetCoreServiceClient()
3028 if err != nil || cClient == nil {
3029 return nil, err
3030 }
3031 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3032 defer cancel()
3033 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3034}
3035
3036func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3037 cClient, err := dh.coreClient.GetCoreServiceClient()
3038 if err != nil || cClient == nil {
3039 return nil, err
3040 }
3041 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3042 defer cancel()
3043 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3044}
3045
3046func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3047 cClient, err := dh.coreClient.GetCoreServiceClient()
3048 if err != nil || cClient == nil {
3049 return err
3050 }
3051 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3052 defer cancel()
3053 _, err = cClient.DeviceUpdate(subCtx, device)
3054 return err
3055}
3056
khenaidoodc2116e2021-10-19 17:33:19 -04003057func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003058 cClient, err := dh.coreClient.GetCoreServiceClient()
3059 if err != nil || cClient == nil {
3060 return nil, err
3061 }
3062 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3063 defer cancel()
3064 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3065}
3066
khenaidoodc2116e2021-10-19 17:33:19 -04003067func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003068 cClient, err := dh.coreClient.GetCoreServiceClient()
3069 if err != nil || cClient == nil {
3070 return err
3071 }
3072 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3073 defer cancel()
3074 _, err = cClient.SendPacketIn(subCtx, pkt)
3075 return err
3076}
3077
3078func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3079 cClient, err := dh.coreClient.GetCoreServiceClient()
3080 if err != nil || cClient == nil {
3081 return err
3082 }
3083 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3084 defer cancel()
3085 _, err = cClient.PortCreated(subCtx, port)
3086 return err
3087}
3088
khenaidoodc2116e2021-10-19 17:33:19 -04003089func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003090 cClient, err := dh.coreClient.GetCoreServiceClient()
3091 if err != nil || cClient == nil {
3092 return err
3093 }
3094 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3095 defer cancel()
3096 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3097 return err
3098}
3099
khenaidoodc2116e2021-10-19 17:33:19 -04003100func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003101 cClient, err := dh.coreClient.GetCoreServiceClient()
3102 if err != nil || cClient == nil {
3103 return err
3104 }
3105 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3106 defer cancel()
3107 _, err = cClient.PortStateUpdate(subCtx, portState)
3108 return err
3109}
3110
khenaidoodc2116e2021-10-19 17:33:19 -04003111func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003112 cClient, err := dh.coreClient.GetCoreServiceClient()
3113 if err != nil || cClient == nil {
3114 return nil, err
3115 }
3116 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3117 defer cancel()
3118 return cClient.GetDevicePort(subCtx, portFilter)
3119}
3120
3121/*
3122Helper functions to communicate with child adapter
3123*/
3124
khenaidoodc2116e2021-10-19 17:33:19 -04003125func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003126 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3127 if err != nil || aClient == nil {
3128 return err
3129 }
3130 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3131 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3132 defer cancel()
3133 _, err = aClient.OmciIndication(subCtx, response)
3134 return err
3135}
3136
khenaidoodc2116e2021-10-19 17:33:19 -04003137func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003138 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3139 if err != nil || aClient == nil {
3140 return err
3141 }
3142 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3143 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3144 defer cancel()
3145 _, err = aClient.OnuIndication(subCtx, onuInd)
3146 return err
3147}
3148
khenaidoodc2116e2021-10-19 17:33:19 -04003149func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003150 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3151 if err != nil || aClient == nil {
3152 return err
3153 }
3154 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3155 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3156 defer cancel()
3157 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3158 return err
3159}
3160
khenaidoodc2116e2021-10-19 17:33:19 -04003161func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003162 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3163 if err != nil || aClient == nil {
3164 return err
3165 }
3166 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3167 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3168 defer cancel()
3169 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3170 return err
3171}
3172
khenaidoodc2116e2021-10-19 17:33:19 -04003173func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003174 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3175 if err != nil || aClient == nil {
3176 return err
3177 }
3178 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3179 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3180 defer cancel()
3181 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3182 return err
3183}
3184
3185/*
3186Helper functions for remote communication
3187*/
3188
3189// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3190// supports is deleted
3191func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3192 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3193
3194 dh.lockChildAdapterClients.Lock()
3195 defer dh.lockChildAdapterClients.Unlock()
3196 if _, ok := dh.childAdapterClients[endpoint]; ok {
3197 // Already set
3198 return nil
3199 }
3200
3201 // Setup child's adapter grpc connection
3202 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003203 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3204 dh.cfg.AdapterEndpoint,
3205 endpoint,
3206 dh.onuAdapterRestarted); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003207 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3208 return err
3209 }
khenaidoo27e7ac92021-12-08 14:43:09 -05003210 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.setAndTestOnuInterAdapterServiceHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003211
3212 // Wait until we have a connection to the child adapter.
3213 // Unlimited retries or until context expires
3214 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3215 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3216 for {
3217 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3218 if err == nil && client != nil {
3219 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3220 break
3221 }
3222 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3223 // Backoff
3224 if err = backoff.Backoff(subCtx); err != nil {
3225 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3226 break
3227 }
3228 }
3229 return nil
3230}
3231
khenaidoodc2116e2021-10-19 17:33:19 -04003232func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003233
3234 // First check from cache
3235 dh.lockChildAdapterClients.RLock()
3236 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3237 dh.lockChildAdapterClients.RUnlock()
3238 return cgClient.GetOnuInterAdapterServiceClient()
3239 }
3240 dh.lockChildAdapterClients.RUnlock()
3241
3242 // Set the child connection - can occur on restarts
3243 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3244 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3245 cancel()
3246 if err != nil {
3247 return nil, err
3248 }
3249
3250 // Get the child client now
3251 dh.lockChildAdapterClients.RLock()
3252 defer dh.lockChildAdapterClients.RUnlock()
3253 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3254 return cgClient.GetOnuInterAdapterServiceClient()
3255 }
3256 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3257}
3258
3259func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3260 dh.lockChildAdapterClients.Lock()
3261 defer dh.lockChildAdapterClients.Unlock()
3262 for key, client := range dh.childAdapterClients {
3263 client.Stop(ctx)
3264 delete(dh.childAdapterClients, key)
3265 }
3266}
3267
3268// TODO: Any action the adapter needs to do following a onu adapter restart?
3269func (dh *DeviceHandler) onuAdapterRestarted(ctx context.Context, endPoint string) error {
khenaidoo7eb2d672021-10-22 19:08:50 -04003270 logger.Warnw(ctx, "onu-adapter-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003271 return nil
3272}
3273
khenaidoo27e7ac92021-12-08 14:43:09 -05003274// setAndTestOnuInterAdapterServiceHandler is used to test whether the remote gRPC service is up
3275func (dh *DeviceHandler) setAndTestOnuInterAdapterServiceHandler(ctx context.Context, conn *grpc.ClientConn, clientConn *common.Connection) interface{} {
3276 // The onu adapter needs to know whether the olt adapter can connect to it. Since the olt adapter
3277 // has a grpc client connection per device handler (i.e. per olt device) to the onu adapter
3278 // then the onu adapter needs to know whether that specific client can connect to it. Because the
3279 // client uses a polling mechanism then not all grpc clients could be connected at the same time,
3280 // a maximum difference of 5 sec. We therefore add the parent device as additional contextual information
3281 // to this request.
3282 dh.lockDevice.RLock()
3283 if dh.device != nil {
3284 clientConn.ContextInfo = dh.device.Id
3285 }
3286 dh.lockDevice.RUnlock()
khenaidoodc2116e2021-10-19 17:33:19 -04003287 svc := onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo27e7ac92021-12-08 14:43:09 -05003288 if h, err := svc.GetHealthStatus(ctx, clientConn); err != nil || h.State != health.HealthStatus_HEALTHY {
khenaidoo106c61a2021-08-11 18:05:46 -04003289 return nil
3290 }
3291 return svc
3292}
Girish Gowdra950326e2021-11-05 12:43:24 -07003293
3294func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3295 dh.lockDevice.Lock()
3296 defer dh.lockDevice.Unlock()
3297 dh.isDeviceDeletionInProgress = flag
3298}
3299
3300func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3301 dh.lockDevice.RLock()
3302 defer dh.lockDevice.RUnlock()
3303 return dh.isDeviceDeletionInProgress
3304}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003305
3306// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3307// Returns false if waiting timed out.
3308func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3309 c := make(chan struct{})
3310 go func() {
3311 defer close(c)
3312 wg.Wait()
3313 }()
3314 select {
3315 case <-c:
3316 return true // completed normally
3317 case <-time.After(timeout):
3318 return false // timed out
3319 }
3320}