blob: c17d92e0eb204a57200b48fa99704c1c3bd3909c [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
Girish Gowdra9602eb42020-09-09 15:50:39 -0700947
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700948 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts)
Girish Gowdra9602eb42020-09-09 15:50:39 -0700949 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700950 var i uint32
951 for i = 0; i < dh.totalPonPorts; i++ {
952 // Instantiate resource manager
953 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 -0700954 return olterrors.ErrResourceManagerInstantiating
955 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400956 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700957 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
958 // the KV store to manage mcast group data. Provide the first instance (0th index)
959 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
960 return olterrors.ErrGroupManagerInstantiating
961 }
962 for i = 0; i < dh.totalPonPorts; i++ {
963 // Instantiate flow manager
964 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
965 return olterrors.ErrFlowManagerInstantiating
966 }
Girish Gowdra76a1b092021-07-28 10:07:04 -0700967 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700968 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400969 /* TODO: Instantiate Alarm , stats , BW managers */
970 /* Instantiating Event Manager to handle Alarms and KPIs */
971 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
972
973 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000974 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400975
976 return nil
977
978}
979
Neha Sharma96b7bf22020-06-15 10:37:32 +0000980func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400981 var err error
982 var deviceInfo *oop.DeviceInfo
983
Neha Sharma8f4e4322020-08-06 10:51:53 +0000984 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400985
986 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000987 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400988 }
989 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000990 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400991 }
992
Neha Sharma96b7bf22020-06-15 10:37:32 +0000993 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400994 dh.device.Root = true
995 dh.device.Vendor = deviceInfo.Vendor
996 dh.device.Model = deviceInfo.Model
997 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
998 dh.device.HardwareVersion = deviceInfo.HardwareVersion
999 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1000
1001 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001002 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001003 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001004 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001005 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001006 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001007 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001008 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001009 dh.device.MacAddress = genmac
1010 } else {
1011 dh.device.MacAddress = deviceInfo.DeviceId
1012 }
1013
1014 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001015 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001016 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001017 }
1018
1019 return deviceInfo, nil
1020}
1021
Neha Sharma96b7bf22020-06-15 10:37:32 +00001022func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001023 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301024 for {
1025 select {
1026 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001027 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301028 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001029 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001030
khenaidoo106c61a2021-08-11 18:05:46 -04001031 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001032 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001033 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001034 continue
1035 }
khenaidoo106c61a2021-08-11 18:05:46 -04001036 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301037 // NNI Stats
1038 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001039 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301040 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001041 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001042 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001043 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301044 }
1045 // PON Stats
1046 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001047 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301048 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1049 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001050 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001051 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301052 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001053 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001054
yasin sapli9e4c5092022-02-01 13:52:33 +00001055 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001056 if len(onuGemInfoLst) > 0 {
1057 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001058 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001059 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301060 }
1061 }
1062 }
1063}
1064
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001065//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301066func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001067 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001068 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301069 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301070
1071 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001072 cgClient, err := dh.coreClient.GetCoreServiceClient()
1073 if err != nil {
1074 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1075 return
1076 }
1077
1078 // Now, set the initial PM configuration for that device
1079 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001080 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301081 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301082}
1083
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001085func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1086 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001087 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301088 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001089 HwDesc: "open_pon",
1090 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001091 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001092 },
1093 SwitchFeatures: &of.OfpSwitchFeatures{
1094 NBuffers: 256,
1095 NTables: 2,
1096 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1097 of.OfpCapabilities_OFPC_TABLE_STATS |
1098 of.OfpCapabilities_OFPC_PORT_STATS |
1099 of.OfpCapabilities_OFPC_GROUP_STATS),
1100 },
1101 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301102}
1103
khenaidoo106c61a2021-08-11 18:05:46 -04001104// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001105func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001106 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001107 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001108 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001109 }
khenaidoo106c61a2021-08-11 18:05:46 -04001110 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001111}
1112
Neha Sharma96b7bf22020-06-15 10:37:32 +00001113func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001114 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 -07001115 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001116 var deviceID string
1117 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001118 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001119
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001120 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001121 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001122 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 -07001123 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1124 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001125
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001126 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301127
1128 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1129
Neha Sharma96b7bf22020-06-15 10:37:32 +00001130 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 -07001131 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001132
khenaidoodc2116e2021-10-19 17:33:19 -04001133 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001134 ParentId: dh.device.Id,
1135 OnuId: omciInd.OnuId,
1136 ParentPortNo: ponPort,
1137 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001138 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301139 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001140 "intf-id": omciInd.IntfId,
1141 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001142 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001143 deviceType = onuDevice.Type
1144 deviceID = onuDevice.Id
1145 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001146 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001147 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001148 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001149 } else {
1150 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001151 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 +05301152 deviceType = onuInCache.(*OnuDevice).deviceType
1153 deviceID = onuInCache.(*OnuDevice).deviceID
1154 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001155 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001156 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001157
khenaidoodc2116e2021-10-19 17:33:19 -04001158 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001159 ParentDeviceId: proxyDeviceID,
1160 ChildDeviceId: deviceID,
1161 Message: omciInd.Pkt,
1162 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301163 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001164 "source": dh.openOLT.config.AdapterEndpoint,
1165 "device-type": deviceType,
1166 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001168 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001169 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301171}
1172
khenaidoo106c61a2021-08-11 18:05:46 -04001173// //ProcessInterAdapterMessage sends the proxied messages to the target device
1174// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1175// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001176// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001177// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001178// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001179// return dh.handleInterAdapterOmciMsg(ctx, msg)
1180// }
1181// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1182// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001183
kesavandb9f54fd2021-11-25 20:08:04 +05301184// ProxyOmciRequests sends the proxied OMCI message to the target device
1185func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
1186 if omciMsgs.GetProxyAddress() == nil {
1187 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1188 if err != nil {
1189 return olterrors.NewErrNotFound("onu", log.Fields{
1190 "parent-device-id": dh.device.Id,
1191 "child-device-id": omciMsgs.ChildDeviceId}, err)
1192 }
1193 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1194 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1195 return olterrors.NewErrCommunication("send-failed", log.Fields{
1196 "parent-device-id": dh.device.Id,
1197 "child-device-id": omciMsgs.ChildDeviceId}, err)
1198 }
1199 } else {
1200 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1201 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1202 return olterrors.NewErrCommunication("send-failed", log.Fields{
1203 "parent-device-id": dh.device.Id,
1204 "child-device-id": omciMsgs.ChildDeviceId}, err)
1205 }
1206 }
1207 return nil
1208}
1209
1210func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1211 var intfID uint32
1212 var onuID uint32
1213 var connectStatus common.ConnectStatus_Types
1214 if onuDevice != nil {
1215 intfID = onuDevice.ProxyAddress.GetChannelId()
1216 onuID = onuDevice.ProxyAddress.GetOnuId()
1217 connectStatus = onuDevice.ConnectStatus
1218 } else {
1219 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1220 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1221 connectStatus = omciMsgs.GetConnectStatus()
1222 }
1223 if connectStatus != voltha.ConnectStatus_REACHABLE {
1224 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1225
1226 return olterrors.NewErrCommunication("unreachable", log.Fields{
1227 "intf-id": intfID,
1228 "onu-id": onuID}, nil)
1229 }
1230
1231 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1232 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1233
1234 onuSecOmciMsgList := omciMsgs.GetMessages()
1235
1236 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1237
1238 var omciMessage *oop.OmciMsg
1239 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1240 hex.Encode(hexPkt, onuSecOmciMsg)
1241 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1242
1243 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1244 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1245 //https://jira.opencord.org/browse/VOL-4604
1246 transid := extractOmciTransactionID(onuSecOmciMsg)
1247 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1248 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1249
1250 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1251 if err != nil {
1252 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1253 "intf-id": intfID,
1254 "onu-id": onuID,
1255 "message": omciMessage}, err)
1256 }
1257 }
1258 return nil
1259}
1260
khenaidoo106c61a2021-08-11 18:05:46 -04001261// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001262func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001263 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 -07001264
1265 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001266 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001267 if err != nil {
1268 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001269 "parent-device-id": dh.device.Id,
1270 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001271 }
khenaidoo106c61a2021-08-11 18:05:46 -04001272 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1273 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001274 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001275 "parent-device-id": dh.device.Id,
1276 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001277 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001278 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001279 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1280 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001281 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001282 "parent-device-id": dh.device.Id,
1283 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001284 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001285 }
1286 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301287}
1288
khenaidoodc2116e2021-10-19 17:33:19 -04001289func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001290 var intfID uint32
1291 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001292 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001293 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001294 intfID = onuDevice.ProxyAddress.GetChannelId()
1295 onuID = onuDevice.ProxyAddress.GetOnuId()
1296 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001297 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001298 intfID = omciMsg.GetProxyAddress().GetChannelId()
1299 onuID = omciMsg.GetProxyAddress().GetOnuId()
1300 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001301 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001302 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001303 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 -08001304
Thomas Lee S94109f12020-03-03 16:39:29 +05301305 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001306 "intf-id": intfID,
1307 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001308 }
1309
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001310 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1311 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301312 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001313 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001314 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1315 hex.Encode(hexPkt, omciMsg.Message)
1316 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1317
1318 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1319 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1320 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001321 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001322 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001323
Neha Sharma8f4e4322020-08-06 10:51:53 +00001324 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001325 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301326 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001327 "intf-id": intfID,
1328 "onu-id": onuID,
1329 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001330 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001331 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001332}
1333
David K. Bainbridge794735f2020-02-11 21:01:37 -08001334func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301335 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 +00001336 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001337 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001338 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001339 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301340 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301341 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001342 st, _ := status.FromError(err)
1343 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001344 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1345
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001346 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301347 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001348 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001349 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001350 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001351 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001352 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001353}
1354
Mahir Gunyelb0046752021-02-26 13:51:05 -08001355func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001356 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001357 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001358
Mahir Gunyelb0046752021-02-26 13:51:05 -08001359 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001360 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301361
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301362 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001363 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001364 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301365
1366 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1367 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1368 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1369 OnuLosRaise event sent for it */
1370 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1371 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1372 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001373 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301374 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1375 "currentIntfId": onuDiscInd.GetIntfId()})
1376 // TODO:: Should we need to ignore raising OnuLosClear event
1377 // when onu connected to different PON?
1378 }
1379 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1380 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1381 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001382 go func() {
1383 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001384 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001385 }
1386 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301387 }
1388 return true
1389 })
1390
Neha Sharma96b7bf22020-06-15 10:37:32 +00001391 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001392 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001393 }
1394
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001395 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001396
1397 // check the ONU is already know to the OLT
1398 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001399 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001400 ParentId: dh.device.Id,
1401 SerialNumber: sn,
1402 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001403
1404 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001405 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 -08001406 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001407 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 -08001408 switch e.Code() {
1409 case codes.Internal:
1410 // this probably means NOT FOUND, so just create a new device
1411 onuDevice = nil
1412 case codes.DeadlineExceeded:
1413 // if the call times out, cleanup and exit
1414 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001415 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001416 }
1417 }
1418 }
1419
1420 if onuDevice == nil {
1421 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001422 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001423 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001424 ponintfid := onuDiscInd.GetIntfId()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001425 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001426
Neha Sharma96b7bf22020-06-15 10:37:32 +00001427 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001428
1429 if err != nil {
1430 // if we can't create an ID in resource manager,
1431 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001432 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001433 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001434 "pon-intf-id": ponintfid,
1435 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001436 }
1437
khenaidoodc2116e2021-10-19 17:33:19 -04001438 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001439 ParentId: dh.device.Id,
1440 ParentPortNo: parentPortNo,
1441 ChannelId: channelID,
1442 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1443 SerialNumber: sn,
1444 OnuId: onuID,
1445 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001446 dh.discOnus.Delete(sn)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001447 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 +05301448 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001449 "pon-intf-id": ponintfid,
1450 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001451 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001452 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 -07001453 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001454 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001455 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301456 log.Fields{"onuDevice": onuDevice,
1457 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001458 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301459 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001460 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001461
khenaidoo106c61a2021-08-11 18:05:46 -04001462 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1463 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1464 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1465 cancel()
1466 if err != nil {
1467 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1468 }
1469
Matteo Scandolo945e4012019-12-12 14:16:11 -08001470 // we can now use the existing ONU Id
1471 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001472 //Insert the ONU into cache to use in OnuIndication.
1473 //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 +00001474 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001475 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301476 "intfId": onuDiscInd.GetIntfId(),
1477 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001478 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001479
khenaidoo106c61a2021-08-11 18:05:46 -04001480 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301481 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001482 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301483 log.Fields{"onu": onuDev,
1484 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001485
khenaidoodc2116e2021-10-19 17:33:19 -04001486 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001487 DeviceId: onuDevice.Id,
1488 ParentDeviceId: dh.device.Id,
1489 OperStatus: common.OperStatus_DISCOVERED,
1490 ConnStatus: common.ConnectStatus_REACHABLE,
1491 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301492 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001493 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001494 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001495 }
khenaidoo106c61a2021-08-11 18:05:46 -04001496
Neha Sharma96b7bf22020-06-15 10:37:32 +00001497 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001498 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301499 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001500 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001501 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001502 }
1503 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001504}
1505
Mahir Gunyelb0046752021-02-26 13:51:05 -08001506func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001507
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001508 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001509 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001510 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001511 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001512 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301513 log.Fields{"onuId": onuInd.OnuId,
1514 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301515 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001516 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001517 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301518
David K. Bainbridge794735f2020-02-11 21:01:37 -08001519 errFields := log.Fields{"device-id": dh.device.Id}
1520
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301521 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1522
Mahir Gunyele77977b2019-06-27 05:36:22 -07001523 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1524 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001525 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001526 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001527 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001528 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1529 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001530 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001531 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001532 errFields["onu-id"] = onuInd.OnuId
1533 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001534 }
khenaidoodc2116e2021-10-19 17:33:19 -04001535 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001536 ParentId: dh.device.Id,
1537 SerialNumber: serialNumber,
1538 OnuId: onuInd.OnuId,
1539 ParentPortNo: ponPort,
1540 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001541 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001542
David K. Bainbridge794735f2020-02-11 21:01:37 -08001543 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001544 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001545 }
1546
David K. Bainbridge794735f2020-02-11 21:01:37 -08001547 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001548 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001549 "previousIntfId": onuDevice.ParentPortNo,
1550 "currentIntfId": ponPort})
1551 }
1552
1553 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001554 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301555 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1556 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301557 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001558 }
1559 if !foundInCache {
1560 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1561
khenaidoo106c61a2021-08-11 18:05:46 -04001562 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 -08001563
1564 }
kesavand7cf3a052020-08-28 12:49:18 +05301565 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001566 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001567 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301568 }
1569 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001571 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001572 }
1573 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001574}
1575
Neha Sharma96b7bf22020-06-15 10:37:32 +00001576func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001577 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 -07001578 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1579 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1580 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1581 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001582 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001583 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1584 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001585 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001586 onuInd.OperState = "down"
1587 }
1588 }
1589
David K. Bainbridge794735f2020-02-11 21:01:37 -08001590 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001591 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001592 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 -04001593
khenaidoodc2116e2021-10-19 17:33:19 -04001594 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001595 DeviceId: onuDevice.Id,
1596 OnuIndication: onuInd,
1597 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001598 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301599 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001601 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001602 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001603 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001604 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001606 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001607 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001608 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001609}
1610
cuilin20187b2a8c32019-03-26 19:52:28 -07001611func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1612 if serialNum != nil {
1613 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001614 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001615 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001616}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001617func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1618 decodedStr, err := hex.DecodeString(serialNum[4:])
1619 if err != nil {
1620 return nil, err
1621 }
1622 return &oop.SerialNumber{
1623 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001624 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001625 }, nil
1626}
cuilin20187b2a8c32019-03-26 19:52:28 -07001627
1628func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001629 if len(vendorSpecific) > 3 {
1630 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1631 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1632 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1633 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1634 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1635 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1636 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1637 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1638 return tmp
1639 }
1640 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001641}
1642
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001643//UpdateFlowsBulk upates the bulk flow
1644func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301645 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001646}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001647
1648//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001649func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1650 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301651 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001652 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301653 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001654
khenaidoodc2116e2021-10-19 17:33:19 -04001655 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001656 ParentId: dh.device.Id,
1657 OnuId: onuID,
1658 ParentPortNo: parentPort,
1659 })
1660
Girish Gowdru0c588b22019-04-23 23:24:56 -04001661 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001662 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001663 "intf-id": parentPort,
1664 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001665 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001666 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 -08001667 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301668}
1669
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001670// SendPacketInToCore sends packet-in to core
1671// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1672// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001674 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001675 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001676 "port": logicalPort,
1677 "packet": hex.EncodeToString(packetPayload),
1678 "device-id": dh.device.Id,
1679 })
1680 }
khenaidoo106c61a2021-08-11 18:05:46 -04001681
khenaidoodc2116e2021-10-19 17:33:19 -04001682 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001683 DeviceId: dh.device.Id,
1684 Port: logicalPort,
1685 Packet: packetPayload,
1686 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301687 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001688 "source": "adapter",
1689 "destination": "core",
1690 "device-id": dh.device.Id,
1691 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001692 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001693 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001694 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001695 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001696 "packet": hex.EncodeToString(packetPayload),
1697 "device-id": dh.device.Id,
1698 })
1699 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001700 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001701}
1702
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001703// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001704func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001705 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001706
1707 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1708 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001709 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001710 }
1711
Kent Hagermane6ff1012020-07-14 15:07:53 -04001712 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001713 metrics := dh.metrics.GetSubscriberMetrics()
1714 for _, m := range pmConfigs.Metrics {
1715 metrics[m.Name].Enabled = m.Enabled
1716
1717 }
1718 }
1719}
1720
khenaidoodc2116e2021-10-19 17:33:19 -04001721func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001722 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001723 var errorsList []error
1724
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001725 if dh.getDeviceDeletionInProgressFlag() {
1726 // The device itself is going to be reset as part of deletion. So nothing to be done.
1727 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1728 return nil
1729 }
1730
Girish Gowdru0c588b22019-04-23 23:24:56 -04001731 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001732 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001733 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001734
Neha Sharma96b7bf22020-06-15 10:37:32 +00001735 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301736 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001737 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301738 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001739 if flow_utils.HasGroup(flow) {
1740 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1741 } else {
1742 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1743 }
Girish Gowdracefae192020-03-19 18:14:10 -07001744 if err != nil {
1745 errorsList = append(errorsList, err)
1746 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001747 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301748
1749 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001750 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001751 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301752 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001753 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301754 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001755 if flow_utils.HasGroup(flow) {
1756 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1757 } else {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001758 if dh.flowMgr == nil || dh.flowMgr[ponIf] == nil {
1759 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1760 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1761 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1762 } else {
1763 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1764 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001765 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001766 if err != nil {
1767 errorsList = append(errorsList, err)
1768 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301769 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001770 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001771
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001772 return errorsList
1773}
1774
1775func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1776 var err error
1777 var errorsList []error
1778
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001779 if dh.getDeviceDeletionInProgressFlag() {
1780 // The device itself is going to be reset as part of deletion. So nothing to be done.
1781 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1782 return nil
1783 }
1784
Girish Gowdracefae192020-03-19 18:14:10 -07001785 // 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 +00001786 if groups != nil {
1787 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001788 // err = dh.groupMgr.AddGroup(ctx, group)
1789 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001790 if err != nil {
1791 errorsList = append(errorsList, err)
1792 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001793 }
1794 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001795 // err = dh.groupMgr.ModifyGroup(ctx, group)
1796 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001797 if err != nil {
1798 errorsList = append(errorsList, err)
1799 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001800 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001801 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001802 // err = dh.groupMgr.DeleteGroup(ctx, group)
1803 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001804 if err != nil {
1805 errorsList = append(errorsList, err)
1806 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001807 }
1808 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001809
1810 return errorsList
1811}
1812
1813//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001814func (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 -07001815
1816 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001817
1818 if dh.getDeviceDeletionInProgressFlag() {
1819 // The device itself is going to be reset as part of deletion. So nothing to be done.
1820 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1821 return nil
1822 }
1823
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001824 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1825 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1826 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001827 if len(errorsList) > 0 {
1828 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1829 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001831 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301832}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001833
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001834//DisableDevice disables the given device
1835//It marks the following for the given device:
1836//Device-Handler Admin-State : down
1837//Device Port-State: UNKNOWN
1838//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001839func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001840 /* On device disable ,admin state update has to be done prior sending request to agent since
1841 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001842 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001843 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001844 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001845 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001846 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001847 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001848 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001850 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001851 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301852
1853 dh.discOnus = sync.Map{}
1854 dh.onus = sync.Map{}
1855
Thomas Lee S85f37312020-04-03 17:06:12 +05301856 //stopping the stats collector
1857 dh.stopCollector <- true
1858
Neha Sharma96b7bf22020-06-15 10:37:32 +00001859 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001860 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301861 //Update device Admin state
1862 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001863
kdarapu1afeceb2020-02-12 01:38:09 -05001864 // 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 -04001865 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001866 DeviceId: cloned.Id,
1867 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
1868 OperStatus: voltha.OperStatus_UNKNOWN,
1869 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001870 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001871 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001872 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001873 return nil
1874}
1875
Neha Sharma96b7bf22020-06-15 10:37:32 +00001876func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001877 // Update onu state as unreachable in onu adapter
1878 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301879 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04001880
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001881 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001882 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001883 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001884 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 -04001885 }
1886 if onuDevices != nil {
1887 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04001888 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001889 DeviceId: onuDevice.Id,
1890 OnuIndication: &onuInd,
1891 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001892 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001893 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001894 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001895 }
1896
1897 }
1898 }
1899
1900}
1901
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001902//ReenableDevice re-enables the olt device after disable
1903//It marks the following for the given device:
1904//Device-Handler Admin-State : up
1905//Device Port-State: ACTIVE
1906//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001907func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001908 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301909 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001910 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301911 }
1912 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001913 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001914
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001915 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04001916 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001917 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001918 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001919 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
1920 } else {
1921 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1922 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
1923 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001924 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001925 if retError == nil {
1926 //Update the device oper status as ACTIVE
1927 device.OperStatus = voltha.OperStatus_ACTIVE
1928 } else {
1929 //Update the device oper status as FAILED
1930 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001931 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001932 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001933
khenaidoodc2116e2021-10-19 17:33:19 -04001934 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001935 DeviceId: device.Id,
1936 OperStatus: device.OperStatus,
1937 ConnStatus: device.ConnectStatus,
1938 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301939 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001940 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001941 "connect-status": device.ConnectStatus,
1942 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001943 }
kesavand39e0aa32020-01-28 20:58:50 -05001944
Neha Sharma96b7bf22020-06-15 10:37:32 +00001945 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001946
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001947 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001948}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001949
npujarec5762e2020-01-01 14:08:48 +05301950func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001951 var uniID uint32
1952 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301953 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001954 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001955 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001956 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001957 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001958 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001959 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001960 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001961 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001962 for _, tpID := range tpIDList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001963 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001964 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001965 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001966 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001967 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001968 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001969 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001970 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301971 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001972 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1973 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001974 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301975 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001976 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001977 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001978 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 +00001979 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001980 }
1981 return nil
1982}
1983
Devmalya Paul495b94a2019-08-27 19:42:00 -04001984// 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 +05301985func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001986 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001987 /* Clear the KV store data associated with the all the UNI ports
1988 This clears up flow data and also resource map data for various
1989 other pon resources like alloc_id and gemport_id
1990 */
Girish Gowdra950326e2021-11-05 12:43:24 -07001991
1992 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001993 var wg sync.WaitGroup
1994 wg.Add(1) // for the mcast routine below to finish
1995 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
1996 for _, flMgr := range dh.flowMgr {
1997 wg.Add(1) // for the flow handler routine below to finish
1998 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
1999 }
2000 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2001 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2002 } else {
2003 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2004 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002005
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002006 dh.cleanupDeviceResources(ctx)
2007 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 -04002008 // Stop the Stats collector
2009 dh.stopCollector <- true
2010 // stop the heartbeat check routine
2011 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05302012 dh.lockDevice.RLock()
2013 // Stop the read indication only if it the routine is active
2014 if dh.isReadIndicationRoutineActive {
2015 dh.stopIndications <- true
2016 }
2017 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002018 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002019 //Reset the state
2020 if dh.Client != nil {
2021 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302022 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002023 }
2024 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002025 // There is no need to update the core about operation status and connection status of the OLT.
2026 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2027 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2028 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002029
khenaidoo7eb2d672021-10-22 19:08:50 -04002030 // Stop the adapter grpc clients for that parent device
2031 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002032 return nil
2033}
Kent Hagermane6ff1012020-07-14 15:07:53 -04002034func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002035
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002036 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302037 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002038 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002039 var err error
yasin sapli9e4c5092022-02-01 13:52:33 +00002040 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002041 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002042 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002043 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002044 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302045 }
2046 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002047 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx, ponPort)
2048 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx, ponPort)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002049 dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002050 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2051 logger.Debug(ctx, err)
2052 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002053 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002054 }
A R Karthick1f85b802019-10-11 05:06:05 +00002055
Devmalya Paul495b94a2019-08-27 19:42:00 -04002056 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302057 dh.onus.Range(func(key interface{}, value interface{}) bool {
2058 dh.onus.Delete(key)
2059 return true
2060 })
2061
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002062 /*Delete discovered ONU map for the device*/
2063 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2064 dh.discOnus.Delete(key)
2065 return true
2066 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002067}
2068
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002069//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002070func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002071 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302072 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002073 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002074 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002075 return nil
2076}
2077
David K. Bainbridge794735f2020-02-11 21:01:37 -08002078func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002079 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002080 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002081 "packet-indication": *packetIn,
2082 "device-id": dh.device.Id,
2083 "packet": hex.EncodeToString(packetIn.Pkt),
2084 })
2085 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002086 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002087 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002088 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002089 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002090 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002091 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002092 "logical-port-num": logicalPortNum,
2093 "device-id": dh.device.Id,
2094 "packet": hex.EncodeToString(packetIn.Pkt),
2095 })
2096 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002097
khenaidoodc2116e2021-10-19 17:33:19 -04002098 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002099 DeviceId: dh.device.Id,
2100 Port: logicalPortNum,
2101 Packet: packetIn.Pkt,
2102 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302103 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002104 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302105 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002106 "device-id": dh.device.Id,
2107 "packet": hex.EncodeToString(packetIn.Pkt),
2108 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002109 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002110
Matteo Scandolo92186242020-06-12 10:54:18 -07002111 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002112 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002113 "packet": hex.EncodeToString(packetIn.Pkt),
2114 "device-id": dh.device.Id,
2115 })
2116 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002117 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002118}
2119
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002120// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002121func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002122 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002123 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002124 "device-id": dh.device.Id,
2125 "egress-port-no": egressPortNo,
2126 "pkt-length": len(packet.Data),
2127 "packet": hex.EncodeToString(packet.Data),
2128 })
2129 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002130
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002131 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002132 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002133 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2134 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302135 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2136 // Do not packet-out lldp packets on uni port.
2137 // ONOS has no clue about uni/nni ports, it just packets out on all
2138 // available ports on the Logical Switch. It should not be interested
2139 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002140 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002141 "device-id": dh.device.Id,
2142 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302143 return nil
2144 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002145 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2146 if innerEthType == 0x8100 {
2147 // q-in-q 802.1ad or 802.1q double tagged packet.
2148 // slice out the outer tag.
2149 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002150 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002151 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002152 "packet-data": hex.EncodeToString(packet.Data),
2153 "device-id": dh.device.Id,
2154 })
2155 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002156 }
2157 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002158 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2159 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2160 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002161
Girish Gowdra9602eb42020-09-09 15:50:39 -07002162 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002163 if err != nil {
2164 // In this case the openolt agent will receive the gemPortID as 0.
2165 // The agent tries to retrieve the gemPortID in this case.
2166 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002167 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002168 "intf-id": intfID,
2169 "onu-id": onuID,
2170 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002171 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302172 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002173 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002174 }
2175
2176 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002177 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002178 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002179 "egress-port-no": egressPortNo,
2180 "intf-id": intfID,
2181 "onu-id": onuID,
2182 "uni-id": uniID,
2183 "gem-port-id": gemPortID,
2184 "packet": hex.EncodeToString(packet.Data),
2185 "device-id": dh.device.Id,
2186 })
2187 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002188
npujarec5762e2020-01-01 14:08:48 +05302189 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302190 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002191 "source": "adapter",
2192 "destination": "onu",
2193 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002194 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002195 "oni-id": onuID,
2196 "uni-id": uniID,
2197 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002198 "packet": hex.EncodeToString(packet.Data),
2199 "device-id": dh.device.Id,
2200 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002201 }
2202 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002203 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002204 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002205 return olterrors.NewErrInvalidValue(log.Fields{
2206 "egress-nni-port": egressPortNo,
2207 "device-id": dh.device.Id,
2208 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002209 }
2210 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002211
Matteo Scandolo92186242020-06-12 10:54:18 -07002212 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002213 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002214 "uplink-pkt": uplinkPkt,
2215 "packet": hex.EncodeToString(packet.Data),
2216 "device-id": dh.device.Id,
2217 })
2218 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002219
npujarec5762e2020-01-01 14:08:48 +05302220 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002221 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2222 "packet": hex.EncodeToString(packet.Data),
2223 "device-id": dh.device.Id,
2224 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002225 }
2226 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002227 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302228 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002229 "egressPortType": egressPortType,
2230 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302231 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002232 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002233 }
2234 return nil
2235}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002236
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002237func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2238 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002239}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302240
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002241func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002242
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302243 // start the heartbeat check towards the OLT.
2244 var timerCheck *time.Timer
2245
2246 for {
2247 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2248 select {
2249 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002250 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002251 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002252 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302253 if timerCheck == nil {
2254 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002255 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302256 }
2257 } else {
2258 if timerCheck != nil {
2259 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002260 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302261 }
2262 timerCheck = nil
2263 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002264 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302265 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302266 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302267 }
2268 cancel()
2269 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002270 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302271 return
2272 }
2273 }
2274}
2275
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002276func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002277 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002278 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002279 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2280 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2281 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2282 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2283 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002284 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002285 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2286 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002287 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302288
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002289 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2290 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002291 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002292 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002293 DeviceId: dh.device.Id,
2294 OperStatus: voltha.OperStatus_UNKNOWN,
2295 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2296 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002297 _ = 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 -04002298 }
khenaidoo106c61a2021-08-11 18:05:46 -04002299
khenaidoodc2116e2021-10-19 17:33:19 -04002300 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002301 DeviceId: dh.device.Id,
2302 PortTypeFilter: 0,
2303 OperStatus: voltha.OperStatus_UNKNOWN,
2304 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002305 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002306 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002307
2308 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002309 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002310 cloned := proto.Clone(device).(*voltha.Device)
2311 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2312 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2313 dh.device = cloned // update local copy of the device
2314 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002315
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002316 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002317 // Stop the Stats collector
2318 dh.stopCollector <- true
2319 // stop the heartbeat check routine
2320 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002321
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002322 dh.lockDevice.RLock()
2323 // Stop the read indication only if it the routine is active
2324 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2325 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2326 // on next execution of the readIndication routine.
2327 if dh.isReadIndicationRoutineActive {
2328 dh.stopIndications <- true
2329 }
2330 dh.lockDevice.RUnlock()
2331
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002332 var wg sync.WaitGroup
2333 wg.Add(1) // for the multicast handler routine
2334 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002335 for _, flMgr := range dh.flowMgr {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002336 wg.Add(1) // for the flow handler routine
2337 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2338 }
2339 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2340 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2341 } else {
2342 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002343 }
2344
Gamze Abakac2c32a62021-03-11 11:44:18 +00002345 //reset adapter reconcile flag
2346 dh.adapterPreviouslyConnected = false
2347
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002348 dh.transitionMap.Handle(ctx, DeviceInit)
2349
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302350 }
2351}
kesavand39e0aa32020-01-28 20:58:50 -05002352
2353// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2355 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2356 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002357}
2358
2359// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002360func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2361 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2362 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002363}
2364
kdarapu1afeceb2020-02-12 01:38:09 -05002365//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 +00002366func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2367 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002368 if port.GetType() == voltha.Port_ETHERNET_NNI {
2369 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002370 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302371 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302372 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002373 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002374 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002375 }
2376 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002377 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002378 ponIntf := &oop.Interface{IntfId: ponID}
2379 var operStatus voltha.OperStatus_Types
2380 if enablePort {
2381 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302382 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002383
2384 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302385 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002386 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002387 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002388 }
2389 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002390 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002392 } else {
2393 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302394 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002395 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302396 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002397 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002398 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002399 }
2400 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002401 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002403 }
khenaidoodc2116e2021-10-19 17:33:19 -04002404 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002405 DeviceId: dh.device.Id,
2406 PortType: voltha.Port_PON_OLT,
2407 PortNo: port.PortNo,
2408 OperStatus: operStatus,
2409 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302410 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302411 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002412 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002413 }
2414 return nil
2415}
2416
kdarapu1afeceb2020-02-12 01:38:09 -05002417//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002418func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002419 // Disable the port and update the oper_port_status to core
2420 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002421 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002422 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002423 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302424 return olterrors.NewErrAdapter("port-disable-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}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002427 }
2428 }
2429 }
2430 return nil
2431}
2432
2433//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002434func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2435 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2436 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002437 if port.Type == voltha.Port_ETHERNET_NNI {
2438 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002439 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002440 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002441 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002442 }
2443 }
2444 if port.Type == voltha.Port_PON_OLT {
2445 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002446 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002447 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002448 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002449 }
2450 }
2451 }
2452}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002453
2454// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002455func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002456 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002457 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002458 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002459
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002460 var sn *oop.SerialNumber
2461 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002462 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302463 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002464 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302465 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002466 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002467 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002468
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002469 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002470 //clear PON resources associated with ONU
2471 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, intfID, onuID)
2472 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2473 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2474 "device-id": dh.device.Id,
2475 "intf-id": intfID,
2476 "onuID": onuID,
2477 "err": err})
2478 } else {
2479 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
2480 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2481 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2482 "device-id": dh.device.Id,
2483 "onu-device": onu,
2484 "err": err})
2485 }
2486 // Clear flowids for gem cache.
2487 for _, gem := range onuGem.GemPorts {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002488 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, intfID, gem)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002489 }
yasin sapli9e4c5092022-02-01 13:52:33 +00002490 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, intfID, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002491 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2492 "intf-id": intfID,
2493 "onu-device": onu,
2494 "onu-gem": onuGem,
2495 "err": err})
2496 //Not returning error on cleanup.
2497 }
2498 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302499
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002500 }
Himani Chawlabcc95852021-10-27 10:55:40 +05302501 dh.resourceMgr[intfID].FreeonuID(ctx, intfID, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002502 dh.onus.Delete(onuKey)
2503 dh.discOnus.Delete(onuSn)
2504
2505 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002506 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302507 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302508 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002509 "onu-id": onuID}, err).Log()
2510 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002511
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002512 return nil
2513}
Girish Gowdracefae192020-03-19 18:14:10 -07002514
2515func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002516 for _, field := range flow_utils.GetOfbFields(flow) {
2517 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002518 return field.GetPort()
2519 }
2520 }
2521 return InvalidPort
2522}
2523
2524func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002525 for _, action := range flow_utils.GetActions(flow) {
2526 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002527 if out := action.GetOutput(); out != nil {
2528 return out.GetPort()
2529 }
2530 }
2531 }
2532 return InvalidPort
2533}
2534
Girish Gowdracefae192020-03-19 18:14:10 -07002535func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2536 inPort := getInPortFromFlow(flow)
2537 outPort := getOutPortFromFlow(flow)
2538
2539 if inPort == InvalidPort || outPort == InvalidPort {
2540 return inPort, outPort
2541 }
2542
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002543 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002544 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002545 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002546 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002547 return uniPort, outPort
2548 }
2549 }
2550 } else {
2551 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002552 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002553 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002554 return inPort, uniPort
2555 }
2556 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002557 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002558 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002559 return uniPort, outPort
2560 }
2561 }
2562 }
2563
2564 return InvalidPort, InvalidPort
2565}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002566
2567func extractOmciTransactionID(omciPkt []byte) uint16 {
2568 if len(omciPkt) > 3 {
2569 d := omciPkt[0:2]
2570 transid := binary.BigEndian.Uint16(d)
2571 return transid
2572 }
2573 return 0
2574}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002575
2576// StoreOnuDevice stores the onu parameters to the local cache.
2577func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2578 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2579 dh.onus.Store(onuKey, onuDevice)
2580}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002581
khenaidoodc2116e2021-10-19 17:33:19 -04002582func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002583 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002584 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002585 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002586 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002587 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002588 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002589 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002590 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2591 return nil, err
2592 }
2593 ID = device.ProxyAddress.GetOnuId()
2594 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2595 valueparam.Onu = &Onu
2596 valueparam.Value = value
2597
2598 // This API is unsupported until agent patch is added
2599 resp.Unsupported = uint32(value)
2600 _ = ctx
2601
2602 // Uncomment this code once agent changes are complete and tests
2603 /*
2604 resp, err = dh.Client.GetValue(ctx, valueparam)
2605 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002606 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002607 return nil, err
2608 }
2609 */
2610
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002611 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 -08002612 return resp, nil
2613}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002614
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002615func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002616 // Default to PON0
2617 var intfID uint32
2618 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002619 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002620 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002621 }
2622 return intfID
2623}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002624
Mahir Gunyelb0046752021-02-26 13:51:05 -08002625func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2626 dh.perPonOnuIndicationChannelLock.Lock()
2627 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2628 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002629 return ch.indicationChannel
2630 }
2631 channels := onuIndicationChannels{
2632 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002633 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002634 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002635 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002636 stopChannel: make(chan struct{}),
2637 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002638 dh.perPonOnuIndicationChannel[intfID] = channels
2639 dh.perPonOnuIndicationChannelLock.Unlock()
2640 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002641 return channels.indicationChannel
2642
2643}
2644
Mahir Gunyelb0046752021-02-26 13:51:05 -08002645func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2646 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2647 dh.perPonOnuIndicationChannelLock.Lock()
2648 defer dh.perPonOnuIndicationChannelLock.Unlock()
2649 for _, v := range dh.perPonOnuIndicationChannel {
2650 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002651 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002652 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002653}
2654
Mahir Gunyelb0046752021-02-26 13:51:05 -08002655func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2656 ind := onuIndicationMsg{
2657 ctx: ctx,
2658 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002659 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002660 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002661 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002662 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002663}
2664
Mahir Gunyelb0046752021-02-26 13:51:05 -08002665func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002666 for {
2667 select {
2668 // process one indication per onu, before proceeding to the next one
2669 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08002670 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002671 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08002672 "ind": indication})
2673 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002674 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002675 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002676 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2677 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002678 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002679 }
2680 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002681 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002682 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2683 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002684 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002685 }
2686 }
2687 case <-onuChannels.stopChannel:
2688 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2689 close(onuChannels.indicationChannel)
2690 return
2691 }
2692 }
2693}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002694
2695// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2696// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04002697func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002698 if dh.getDeviceDeletionInProgressFlag() {
2699 // The device itself is going to be reset as part of deletion. So nothing to be done.
2700 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2701 return nil
2702 }
2703
Girish Gowdra491a9c62021-01-06 16:43:07 -08002704 // Step1 : Fill McastFlowOrGroupControlBlock
2705 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2706 // Step3 : Wait on response channel for response
2707 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002708 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002709 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2710 errChan := make(chan error)
2711 var groupID uint32
2712 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2713 ctx: ctx,
2714 flowOrGroupAction: action,
2715 flow: flow,
2716 group: group,
2717 errChan: &errChan,
2718 }
2719 if flow != nil {
2720 groupID = flow_utils.GetGroup(flow)
2721 } else if group != nil {
2722 groupID = group.Desc.GroupId
2723 } else {
2724 return errors.New("flow-and-group-both-nil")
2725 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002726 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2727 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2728 // Derive the appropriate go routine to handle the request by a simple module operation.
2729 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2730 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2731 // Wait for handler to return error value
2732 err := <-errChan
2733 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2734 return err
2735 }
2736 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2737 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002738}
2739
2740// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002741func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002742 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002743 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002744 // block on the channel to receive an incoming mcast flow/group
2745 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002746 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2747 if mcastFlowOrGroupCb.flow != nil {
2748 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2749 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2750 log.Fields{"device-id": dh.device.Id,
2751 "flowToAdd": mcastFlowOrGroupCb.flow})
2752 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2753 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2754 // Pass the return value over the return channel
2755 *mcastFlowOrGroupCb.errChan <- err
2756 } else { // flow remove
2757 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2758 log.Fields{"device-id": dh.device.Id,
2759 "flowToRemove": mcastFlowOrGroupCb.flow})
2760 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2761 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2762 // Pass the return value over the return channel
2763 *mcastFlowOrGroupCb.errChan <- err
2764 }
2765 } else { // mcast group
2766 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2767 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2768 log.Fields{"device-id": dh.device.Id,
2769 "groupToAdd": mcastFlowOrGroupCb.group})
2770 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2771 // Pass the return value over the return channel
2772 *mcastFlowOrGroupCb.errChan <- err
2773 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2774 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2775 log.Fields{"device-id": dh.device.Id,
2776 "groupToModify": mcastFlowOrGroupCb.group})
2777 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2778 // Pass the return value over the return channel
2779 *mcastFlowOrGroupCb.errChan <- err
2780 } else { // group remove
2781 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2782 log.Fields{"device-id": dh.device.Id,
2783 "groupToRemove": mcastFlowOrGroupCb.group})
2784 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2785 // Pass the return value over the return channel
2786 *mcastFlowOrGroupCb.errChan <- err
2787 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002788 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002789 case <-stopHandler:
2790 dh.mcastHandlerRoutineActive[routineIndex] = false
2791 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08002792 }
2793 }
2794}
kesavand62126212021-01-12 04:56:06 -05002795
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002796// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002797func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002798 for i, v := range dh.stopMcastHandlerRoutine {
2799 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002800 select {
2801 case v <- true:
2802 case <-time.After(time.Second * 5):
2803 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
2804 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002805 }
2806 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002807 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002808 logger.Debug(ctx, "stopped all mcast handler routines")
2809}
2810
kesavand62126212021-01-12 04:56:06 -05002811func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2812
2813 singleValResp := extension.SingleGetValueResponse{
2814 Response: &extension.GetValueResponse{
2815 Response: &extension.GetValueResponse_PortCoutners{
2816 PortCoutners: &extension.GetOltPortCountersResponse{},
2817 },
2818 },
2819 }
2820
2821 errResp := func(status extension.GetValueResponse_Status,
2822 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2823 return &extension.SingleGetValueResponse{
2824 Response: &extension.GetValueResponse{
2825 Status: status,
2826 ErrReason: reason,
2827 },
2828 }
2829 }
2830
2831 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2832 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2833 //send error response
2834 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2835 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2836 }
2837 statIndChn := make(chan bool, 1)
2838 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2839 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2840 //request openOlt agent to send the the port statistics indication
2841
2842 go func() {
2843 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2844 if err != nil {
2845 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2846 }
2847 }()
2848 select {
2849 case <-statIndChn:
2850 //indication received for ports stats
2851 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2852 case <-time.After(oltPortInfoTimeout * time.Second):
2853 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2854 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2855 case <-ctx.Done():
2856 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2857 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2858 }
2859 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2860 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002861 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05002862 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2863 cmnni := dh.portStats.collectNNIMetrics(intfID)
2864 if cmnni == nil {
2865 //TODO define the error reason
2866 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2867 }
2868 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2869 return &singleValResp
2870
2871 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2872 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002873 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05002874 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2875 cmpon := dh.portStats.collectPONMetrics(intfID)
2876 if cmpon == nil {
2877 //TODO define the error reason
2878 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2879 }
2880 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2881 return &singleValResp
2882 }
2883 }
2884 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2885}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302886
2887func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2888
2889 singleValResp := extension.SingleGetValueResponse{
2890 Response: &extension.GetValueResponse{
2891 Response: &extension.GetValueResponse_OnuPonCounters{
2892 OnuPonCounters: &extension.GetOnuCountersResponse{},
2893 },
2894 },
2895 }
2896
2897 errResp := func(status extension.GetValueResponse_Status,
2898 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2899 return &extension.SingleGetValueResponse{
2900 Response: &extension.GetValueResponse{
2901 Status: status,
2902 ErrReason: reason,
2903 },
2904 }
2905 }
2906 intfID := onuPonInfo.IntfId
2907 onuID := onuPonInfo.OnuId
2908 onuKey := dh.formOnuKey(intfID, onuID)
2909
2910 if _, ok := dh.onus.Load(onuKey); !ok {
2911 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2912 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2913 }
2914 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2915 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2916 if cmnni == nil {
2917 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2918 }
2919 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2920 return &singleValResp
2921
2922}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002923
2924func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2925
2926 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
2927 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
2928 if err != nil {
2929 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
2930 return generateSingleGetValueErrorResponse(err)
2931 }
2932 return &extension.SingleGetValueResponse{
2933 Response: &extension.GetValueResponse{
2934 Status: extension.GetValueResponse_OK,
2935 Response: &extension.GetValueResponse_RxPower{
2936 RxPower: &extension.GetRxPowerResponse{
2937 IntfId: rxPowerRequest.IntfId,
2938 OnuId: rxPowerRequest.OnuId,
2939 Status: rxPower.Status,
2940 FailReason: rxPower.FailReason.String(),
2941 RxPower: rxPower.RxPowerMeanDbm,
2942 },
2943 },
2944 },
2945 }
2946}
2947
2948func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
2949 errResp := func(status extension.GetValueResponse_Status,
2950 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2951 return &extension.SingleGetValueResponse{
2952 Response: &extension.GetValueResponse{
2953 Status: status,
2954 ErrReason: reason,
2955 },
2956 }
2957 }
2958
2959 if err != nil {
2960 if e, ok := status.FromError(err); ok {
2961 switch e.Code() {
2962 case codes.Internal:
2963 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2964 case codes.DeadlineExceeded:
2965 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2966 case codes.Unimplemented:
2967 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
2968 case codes.NotFound:
2969 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2970 }
2971 }
2972 }
2973
2974 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
2975}
khenaidoo106c61a2021-08-11 18:05:46 -04002976
2977/*
2978Helper functions to communicate with Core
2979*/
2980
2981func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
2982 cClient, err := dh.coreClient.GetCoreServiceClient()
2983 if err != nil || cClient == nil {
2984 return nil, err
2985 }
2986 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2987 defer cancel()
2988 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
2989}
2990
khenaidoodc2116e2021-10-19 17:33:19 -04002991func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002992 cClient, err := dh.coreClient.GetCoreServiceClient()
2993 if err != nil || cClient == nil {
2994 return nil, err
2995 }
2996 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2997 defer cancel()
2998 return cClient.GetChildDevice(subCtx, childDeviceFilter)
2999}
3000
khenaidoodc2116e2021-10-19 17:33:19 -04003001func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003002 cClient, err := dh.coreClient.GetCoreServiceClient()
3003 if err != nil || cClient == nil {
3004 return err
3005 }
3006 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3007 defer cancel()
3008 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3009 return err
3010}
3011
3012func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3013 cClient, err := dh.coreClient.GetCoreServiceClient()
3014 if err != nil || cClient == nil {
3015 return nil, err
3016 }
3017 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3018 defer cancel()
3019 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3020}
3021
3022func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3023 cClient, err := dh.coreClient.GetCoreServiceClient()
3024 if err != nil || cClient == nil {
3025 return nil, err
3026 }
3027 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3028 defer cancel()
3029 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3030}
3031
3032func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3033 cClient, err := dh.coreClient.GetCoreServiceClient()
3034 if err != nil || cClient == nil {
3035 return err
3036 }
3037 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3038 defer cancel()
3039 _, err = cClient.DeviceUpdate(subCtx, device)
3040 return err
3041}
3042
khenaidoodc2116e2021-10-19 17:33:19 -04003043func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003044 cClient, err := dh.coreClient.GetCoreServiceClient()
3045 if err != nil || cClient == nil {
3046 return nil, err
3047 }
3048 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3049 defer cancel()
3050 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3051}
3052
khenaidoodc2116e2021-10-19 17:33:19 -04003053func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003054 cClient, err := dh.coreClient.GetCoreServiceClient()
3055 if err != nil || cClient == nil {
3056 return err
3057 }
3058 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3059 defer cancel()
3060 _, err = cClient.SendPacketIn(subCtx, pkt)
3061 return err
3062}
3063
3064func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3065 cClient, err := dh.coreClient.GetCoreServiceClient()
3066 if err != nil || cClient == nil {
3067 return err
3068 }
3069 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3070 defer cancel()
3071 _, err = cClient.PortCreated(subCtx, port)
3072 return err
3073}
3074
khenaidoodc2116e2021-10-19 17:33:19 -04003075func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003076 cClient, err := dh.coreClient.GetCoreServiceClient()
3077 if err != nil || cClient == nil {
3078 return err
3079 }
3080 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3081 defer cancel()
3082 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3083 return err
3084}
3085
khenaidoodc2116e2021-10-19 17:33:19 -04003086func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003087 cClient, err := dh.coreClient.GetCoreServiceClient()
3088 if err != nil || cClient == nil {
3089 return err
3090 }
3091 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3092 defer cancel()
3093 _, err = cClient.PortStateUpdate(subCtx, portState)
3094 return err
3095}
3096
khenaidoodc2116e2021-10-19 17:33:19 -04003097func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003098 cClient, err := dh.coreClient.GetCoreServiceClient()
3099 if err != nil || cClient == nil {
3100 return nil, err
3101 }
3102 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3103 defer cancel()
3104 return cClient.GetDevicePort(subCtx, portFilter)
3105}
3106
3107/*
3108Helper functions to communicate with child adapter
3109*/
3110
khenaidoodc2116e2021-10-19 17:33:19 -04003111func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003112 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3113 if err != nil || aClient == nil {
3114 return err
3115 }
3116 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3117 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3118 defer cancel()
3119 _, err = aClient.OmciIndication(subCtx, response)
3120 return err
3121}
3122
khenaidoodc2116e2021-10-19 17:33:19 -04003123func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003124 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3125 if err != nil || aClient == nil {
3126 return err
3127 }
3128 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3129 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3130 defer cancel()
3131 _, err = aClient.OnuIndication(subCtx, onuInd)
3132 return err
3133}
3134
khenaidoodc2116e2021-10-19 17:33:19 -04003135func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003136 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3137 if err != nil || aClient == nil {
3138 return err
3139 }
3140 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3141 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3142 defer cancel()
3143 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3144 return err
3145}
3146
khenaidoodc2116e2021-10-19 17:33:19 -04003147func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003148 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3149 if err != nil || aClient == nil {
3150 return err
3151 }
3152 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3153 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3154 defer cancel()
3155 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3156 return err
3157}
3158
khenaidoodc2116e2021-10-19 17:33:19 -04003159func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003160 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3161 if err != nil || aClient == nil {
3162 return err
3163 }
3164 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3165 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3166 defer cancel()
3167 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3168 return err
3169}
3170
3171/*
3172Helper functions for remote communication
3173*/
3174
3175// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3176// supports is deleted
3177func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3178 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3179
3180 dh.lockChildAdapterClients.Lock()
3181 defer dh.lockChildAdapterClients.Unlock()
3182 if _, ok := dh.childAdapterClients[endpoint]; ok {
3183 // Already set
3184 return nil
3185 }
3186
3187 // Setup child's adapter grpc connection
3188 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003189 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3190 dh.cfg.AdapterEndpoint,
3191 endpoint,
3192 dh.onuAdapterRestarted); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003193 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3194 return err
3195 }
khenaidoo27e7ac92021-12-08 14:43:09 -05003196 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.setAndTestOnuInterAdapterServiceHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003197
3198 // Wait until we have a connection to the child adapter.
3199 // Unlimited retries or until context expires
3200 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3201 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3202 for {
3203 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3204 if err == nil && client != nil {
3205 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3206 break
3207 }
3208 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3209 // Backoff
3210 if err = backoff.Backoff(subCtx); err != nil {
3211 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3212 break
3213 }
3214 }
3215 return nil
3216}
3217
khenaidoodc2116e2021-10-19 17:33:19 -04003218func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003219
3220 // First check from cache
3221 dh.lockChildAdapterClients.RLock()
3222 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3223 dh.lockChildAdapterClients.RUnlock()
3224 return cgClient.GetOnuInterAdapterServiceClient()
3225 }
3226 dh.lockChildAdapterClients.RUnlock()
3227
3228 // Set the child connection - can occur on restarts
3229 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3230 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3231 cancel()
3232 if err != nil {
3233 return nil, err
3234 }
3235
3236 // Get the child client now
3237 dh.lockChildAdapterClients.RLock()
3238 defer dh.lockChildAdapterClients.RUnlock()
3239 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3240 return cgClient.GetOnuInterAdapterServiceClient()
3241 }
3242 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3243}
3244
3245func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3246 dh.lockChildAdapterClients.Lock()
3247 defer dh.lockChildAdapterClients.Unlock()
3248 for key, client := range dh.childAdapterClients {
3249 client.Stop(ctx)
3250 delete(dh.childAdapterClients, key)
3251 }
3252}
3253
3254// TODO: Any action the adapter needs to do following a onu adapter restart?
3255func (dh *DeviceHandler) onuAdapterRestarted(ctx context.Context, endPoint string) error {
khenaidoo7eb2d672021-10-22 19:08:50 -04003256 logger.Warnw(ctx, "onu-adapter-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003257 return nil
3258}
3259
khenaidoo27e7ac92021-12-08 14:43:09 -05003260// setAndTestOnuInterAdapterServiceHandler is used to test whether the remote gRPC service is up
3261func (dh *DeviceHandler) setAndTestOnuInterAdapterServiceHandler(ctx context.Context, conn *grpc.ClientConn, clientConn *common.Connection) interface{} {
3262 // The onu adapter needs to know whether the olt adapter can connect to it. Since the olt adapter
3263 // has a grpc client connection per device handler (i.e. per olt device) to the onu adapter
3264 // then the onu adapter needs to know whether that specific client can connect to it. Because the
3265 // client uses a polling mechanism then not all grpc clients could be connected at the same time,
3266 // a maximum difference of 5 sec. We therefore add the parent device as additional contextual information
3267 // to this request.
3268 dh.lockDevice.RLock()
3269 if dh.device != nil {
3270 clientConn.ContextInfo = dh.device.Id
3271 }
3272 dh.lockDevice.RUnlock()
khenaidoodc2116e2021-10-19 17:33:19 -04003273 svc := onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo27e7ac92021-12-08 14:43:09 -05003274 if h, err := svc.GetHealthStatus(ctx, clientConn); err != nil || h.State != health.HealthStatus_HEALTHY {
khenaidoo106c61a2021-08-11 18:05:46 -04003275 return nil
3276 }
3277 return svc
3278}
Girish Gowdra950326e2021-11-05 12:43:24 -07003279
3280func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3281 dh.lockDevice.Lock()
3282 defer dh.lockDevice.Unlock()
3283 dh.isDeviceDeletionInProgress = flag
3284}
3285
3286func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3287 dh.lockDevice.RLock()
3288 defer dh.lockDevice.RUnlock()
3289 return dh.isDeviceDeletionInProgress
3290}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003291
3292// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3293// Returns false if waiting timed out.
3294func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3295 c := make(chan struct{})
3296 go func() {
3297 defer close(c)
3298 wg.Wait()
3299 }()
3300 select {
3301 case <-c:
3302 return true // completed normally
3303 case <-time.After(timeout):
3304 return false // timed out
3305 }
3306}