blob: 822d83e3743efd431c7f0c6e7b4639f4c064bbcb [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
Manikkaraj kb1d51442019-07-23 10:41:02 -040072)
73
Phaneendra Manda4c62c802019-03-06 21:37:49 +053074//DeviceHandler will interact with the OLT device.
75type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040076 cm *config.ConfigManager
77 device *voltha.Device
78 cfg *conf.AdapterFlags
79 coreClient *vgrpc.Client
80 childAdapterClients map[string]*vgrpc.Client
81 lockChildAdapterClients sync.RWMutex
82 EventProxy eventif.EventProxy
83 openOLT *OpenOLT
84 exitChannel chan int
85 lockDevice sync.RWMutex
86 Client oop.OpenoltClient
87 transitionMap *TransitionMap
88 clientCon *grpc.ClientConn
89 flowMgr []*OpenOltFlowMgr
90 groupMgr *OpenOltGroupMgr
91 eventMgr *OpenOltEventMgr
92 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070093
94 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053095
Girish Gowdra3ab6d212020-03-24 17:33:15 -070096 discOnus sync.Map
97 onus sync.Map
98 portStats *OpenOltStatisticsMgr
99 metrics *pmmetrics.PmMetrics
100 stopCollector chan bool
101 stopHeartbeatCheck chan bool
102 activePorts sync.Map
103 stopIndications chan bool
104 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700105
Mahir Gunyelb0046752021-02-26 13:51:05 -0800106 totalPonPorts uint32
107 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
108 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800109
110 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
111 // 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 -0700112 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
113 stopMcastHandlerRoutine []chan bool
114 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000115
116 adapterPreviouslyConnected bool
117 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700118
119 isDeviceDeletionInProgress bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700120}
121
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700122//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700123type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400124 deviceID string
125 deviceType string
126 serialNumber string
127 onuID uint32
128 intfID uint32
129 proxyDeviceID string
130 losRaised bool
131 rdiRaised bool
132 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700133}
134
Mahir Gunyelb0046752021-02-26 13:51:05 -0800135type onuIndicationMsg struct {
136 ctx context.Context
137 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800138}
139
140type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800141 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800142 stopChannel chan struct{}
143}
144
Girish Gowdra491a9c62021-01-06 16:43:07 -0800145//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
146//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
147//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
148//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
149type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400150 ctx context.Context // Flow/group handler context
151 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
152 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
153 group *of.OfpGroupEntry // Group message (can be nil or valid group)
154 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800155}
156
Naga Manjunath7615e552019-10-11 22:35:47 +0530157var pmNames = []string{
158 "rx_bytes",
159 "rx_packets",
160 "rx_mcast_packets",
161 "rx_bcast_packets",
162 "tx_bytes",
163 "tx_packets",
164 "tx_mcast_packets",
165 "tx_bcast_packets",
166}
167
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700168//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400169func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700170 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700171 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700172 device.deviceType = deviceTp
173 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700174 device.onuID = onuID
175 device.intfID = intfID
176 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530177 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400178 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700179 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530180}
181
182//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400183func 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 -0700184 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800185 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400186 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400187 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700188 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700189 dh.device = cloned
190 dh.openOLT = adapter
Girish Gowdraae56c722021-11-22 14:31:11 -0800191 dh.exitChannel = make(chan int, 1) // TODO: Why buffered?
cuilin20187b2a8c32019-03-26 19:52:28 -0700192 dh.lockDevice = sync.RWMutex{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800193 dh.stopCollector = make(chan bool, 2) // TODO: Why buffered?
194 dh.stopHeartbeatCheck = make(chan bool, 2) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530195 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 -0500196 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800197 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800198 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400199 dh.childAdapterClients = make(map[string]*vgrpc.Client)
200 dh.cfg = cfg
Girish Gowdra491a9c62021-01-06 16:43:07 -0800201 // Create a slice of buffered channels for handling concurrent mcast flow/group.
202 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700203 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
204 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800205 for i := range dh.incomingMcastFlowOrGroup {
206 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800207 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800208 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
209 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
210 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
211 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700212 dh.mcastHandlerRoutineActive[i] = true
213 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800214 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700215 //TODO initialize the support classes.
216 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530217}
218
219// start save the device to the data model
220func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700221 dh.lockDevice.Lock()
222 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000223 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700224 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000225 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530226}
227
228// stop stops the device dh. Not much to do for now
229func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700230 dh.lockDevice.Lock()
231 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000232 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700233 dh.exitChannel <- 1
khenaidoo106c61a2021-08-11 18:05:46 -0400234
Neha Sharma96b7bf22020-06-15 10:37:32 +0000235 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530236}
237
ssiddiqui04386ee2021-08-23 21:58:25 +0530238func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
239 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
240 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
241 if pooledIntfID == intfID {
242 return resourceRanges.GetTechnology()
243 }
244 }
245 }
246 return ""
247}
248
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400249func macifyIP(ip net.IP) string {
250 if len(ip) > 0 {
251 oct1 := strconv.FormatInt(int64(ip[12]), 16)
252 oct2 := strconv.FormatInt(int64(ip[13]), 16)
253 oct3 := strconv.FormatInt(int64(ip[14]), 16)
254 oct4 := strconv.FormatInt(int64(ip[15]), 16)
255 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
256 }
257 return ""
258}
259
Neha Sharma96b7bf22020-06-15 10:37:32 +0000260func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400261 var genmac string
262 var addr net.IP
263 var ips []string
264 var err error
265
Neha Sharma96b7bf22020-06-15 10:37:32 +0000266 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400267
268 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000269 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400270
271 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000272 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400273 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000274 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400275 }
276 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000277 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530278 log.Fields{"host": ips[0],
279 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400280 return genmac, nil
281 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000282 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400283 }
284
285 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000286 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530287 log.Fields{"host": host,
288 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400289 return genmac, nil
290}
291
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530292func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700293 slist := strings.Split(mac, ":")
294 result := make([]uint32, len(slist))
295 var err error
296 var tmp int64
297 for index, val := range slist {
298 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
299 return []uint32{1, 2, 3, 4, 5, 6}
300 }
301 result[index] = uint32(tmp)
302 }
303 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530304}
305
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700306//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 -0800307func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530308
David K. Bainbridge794735f2020-02-11 21:01:37 -0800309 switch portType {
310 case voltha.Port_ETHERNET_NNI:
311 return fmt.Sprintf("nni-%d", portNum), nil
312 case voltha.Port_PON_OLT:
313 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700314 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800315
Girish Kumarf26e4882020-03-05 06:49:10 +0000316 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530317}
318
Neha Sharma96b7bf22020-06-15 10:37:32 +0000319func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000320 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700321 if state == "up" {
322 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500323 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500324 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700325 } else {
326 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500327 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700328 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700329 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400330 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800331 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000332 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400333 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500334
khenaidoo106c61a2021-08-11 18:05:46 -0400335 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400336 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400337 DeviceId: dh.device.Id,
338 Port: portNum,
339 })
340 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000341 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400342 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400343 DeviceId: dh.device.Id,
344 PortType: portType,
345 PortNo: portNum,
346 OperStatus: operStatus})
347 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400348 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
349 "device-id": dh.device.Id,
350 "port-type": portType,
351 "port-number": portNum,
352 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500353 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400354 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500355 }
khenaidoo106c61a2021-08-11 18:05:46 -0400356
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400357 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700358 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
khenaidoo106c61a2021-08-11 18:05:46 -0400359 port = &voltha.Port{
360 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700361 PortNo: portNum,
362 Label: label,
363 Type: portType,
364 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700365 OfpPort: &of.OfpPort{
366 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
367 Config: 0,
368 State: uint32(of.OfpPortState_OFPPS_LIVE),
369 Curr: capacity,
370 Advertised: capacity,
371 Peer: capacity,
372 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
373 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
374 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700375 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000376 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700377 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400378 err = dh.createPortInCore(ctx, port)
379 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000380 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800381 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000382 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400383 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000384 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530385 return nil
386}
387
Kent Hagermane6ff1012020-07-14 15:07:53 -0400388func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400389 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530390 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400391 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
392 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530393 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800394 dh.lockDevice.Lock()
395 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530396 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530397}
398
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700399// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530400// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800401func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000402 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700403 defer func() {
404 dh.lockDevice.Lock()
405 dh.isReadIndicationRoutineActive = false
406 dh.lockDevice.Unlock()
407 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700408 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700409 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700410 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700411 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400412
David Bainbridgef5879ca2019-12-13 21:17:54 +0000413 // Create an exponential backoff around re-enabling indications. The
414 // maximum elapsed time for the back off is set to 0 so that we will
415 // continue to retry. The max interval defaults to 1m, but is set
416 // here for code clarity
417 indicationBackoff := backoff.NewExponentialBackOff()
418 indicationBackoff.MaxElapsedTime = 0
419 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700420
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700421 dh.lockDevice.Lock()
422 dh.isReadIndicationRoutineActive = true
423 dh.lockDevice.Unlock()
424
Girish Gowdra3f974912020-03-23 20:35:18 -0700425Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700426 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400427 select {
428 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000429 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700430 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400431 default:
432 indication, err := indications.Recv()
433 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000434 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530435 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530436 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400437 // Use an exponential back off to prevent getting into a tight loop
438 duration := indicationBackoff.NextBackOff()
439 if duration == backoff.Stop {
440 // If we reach a maximum then warn and reset the backoff
441 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000442 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530443 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530444 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400445 indicationBackoff.Reset()
446 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700447
448 // On failure process a backoff timer while watching for stopIndications
449 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700450 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700451 select {
452 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000453 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700454 if !backoffTimer.Stop() {
455 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700456 }
457 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700458 case <-backoffTimer.C:
459 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700460 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700461 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
462 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400463 }
464 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000465 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530466 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000467 logger.Errorw(ctx, "read-indication-error",
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})
Girish Gowdra3f974912020-03-23 20:35:18 -0700470 // Close the stream, and re-initialize it
471 if err = indications.CloseSend(); err != nil {
472 // Ok to ignore here, because we landed here due to a problem on the stream
473 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000474 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530475 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530476 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700477 }
Matteo Scandolof16389e2021-05-18 00:47:08 +0000478 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700479 return err
480 }
481 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400482 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530483 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400484 // Reset backoff if we have a successful receive
485 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400486 // When OLT is admin down, ignore all indications.
Girish Gowdra852ad912021-05-04 00:05:50 -0700487 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000488 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530489 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530490 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400491 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400492 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400493 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700494 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700495 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700496 // Close the send stream
497 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700498
Girish Gowdra3f974912020-03-23 20:35:18 -0700499 return nil
500}
501
502func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700503 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700504 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
505 if err != nil {
506 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
507 }
508 if indications == nil {
509 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
510 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700511 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700512 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400513}
514
515// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
516func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
517 switch indication.Data.(type) {
518 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
519 return true
520
521 default:
522 return false
523 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700524}
525
David K. Bainbridge794735f2020-02-11 21:01:37 -0800526func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700527 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000528 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530529 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700530 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530531 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700532 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000533 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000534 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530535 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000536 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800537 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000538 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800539 }
540 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541}
542
David K. Bainbridge794735f2020-02-11 21:01:37 -0800543// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530544func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700545 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700546 switch indication.Data.(type) {
547 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000548 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
549 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700550 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 -0800551 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400552 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800553 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700554 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000555 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
556 defer span.Finish()
557
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700558 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800559 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400561 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800562 }
563 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000564 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700565 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000566 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
567 defer span.Finish()
568
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700569 intfOperInd := indication.GetIntfOperInd()
570 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800571 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400573 _ = 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 -0800574 }
575 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576 } else if intfOperInd.GetType() == "pon" {
577 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
578 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800579 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000580 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400581 _ = 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 -0800582 }
583 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000584 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700585 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000586 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530587 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530588 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700589 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000590 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
591 defer span.Finish()
592
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700593 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000594 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800595 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800596 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700597 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000598 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
599 defer span.Finish()
600
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700601 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000602 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800603 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800604 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000606 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
607 defer span.Finish()
608
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000610 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 -0800611 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000612 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400613 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800614 }
615 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700616 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000617 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
618 defer span.Finish()
619
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700620 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000621 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700622 "intf-type": pktInd.IntfId,
623 "intf-id": pktInd.IntfId,
624 "gem-port-id": pktInd.GemportId,
625 "port-no": pktInd.PortNo,
626 "device-id": dh.device.Id,
627 })
628
629 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000630 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700631 "intf-type": pktInd.IntfId,
632 "intf-id": pktInd.IntfId,
633 "gem-port-id": pktInd.GemportId,
634 "port-no": pktInd.PortNo,
635 "packet": hex.EncodeToString(pktInd.Pkt),
636 "device-id": dh.device.Id,
637 })
638 }
639
David K. Bainbridge794735f2020-02-11 21:01:37 -0800640 go func() {
641 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400642 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800643 }
644 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700645 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000646 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
647 defer span.Finish()
648
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700649 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700650 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000652 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
653 defer span.Finish()
654
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700655 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000656 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000658 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
659 defer span.Finish()
660
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700661 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000662 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
663 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700664 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530665}
666
667// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530668func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530669 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000670 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530671
Girish Gowdra618fa572021-09-01 17:19:29 -0700672 // instantiate the mcast handler routines.
673 for i := range dh.incomingMcastFlowOrGroup {
674 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
675 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
676 if !dh.mcastHandlerRoutineActive[i] {
677 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
678 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
679 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
680 // for incoming mcast flow/group to be processed serially.
681 dh.mcastHandlerRoutineActive[i] = true
682 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
683 }
684 }
685
Girish Gowdru0c588b22019-04-23 23:24:56 -0400686 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400687 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400688 DeviceId: dh.device.Id,
689 OperStatus: voltha.OperStatus_ACTIVE,
690 ConnStatus: voltha.ConnectStatus_REACHABLE,
691 }); err != nil {
692 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400693 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000694
695 //Clear olt communication failure event
696 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
697 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700698 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000699 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
700
Gamze Abakac2c32a62021-03-11 11:44:18 +0000701 //check adapter and agent reconcile status
702 //reboot olt if needed (olt disconnection case)
703 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
704 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
705 log.Fields{
706 "device-id": dh.device.Id,
707 "adapter-status": dh.adapterPreviouslyConnected,
708 "agent-status": dh.agentPreviouslyConnected,
709 })
710 _ = dh.RebootDevice(ctx, dh.device)
711 }
712
Girish Gowdru0c588b22019-04-23 23:24:56 -0400713 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530714}
715
716// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530717func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000718 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400719
khenaidoo106c61a2021-08-11 18:05:46 -0400720 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400721 if err != nil || device == nil {
722 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000723 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400724 }
725
726 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400727
728 //Update the device oper state and connection status
729 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800730 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400731 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800732 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400733
khenaidoodc2116e2021-10-19 17:33:19 -0400734 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400735 DeviceId: cloned.Id,
736 OperStatus: cloned.OperStatus,
737 ConnStatus: cloned.ConnectStatus,
738 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000739 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400740 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400741
742 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400743 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400744 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000745 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400746 }
747 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400748 // Update onu state as down in onu adapter
749 onuInd := oop.OnuIndication{}
750 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400751
752 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
753 if err != nil {
754 return err
755 }
756 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400757 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400758 DeviceId: onuDevice.Id,
759 OnuIndication: &onuInd,
760 })
761 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800762 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400763 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400764 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800765 "onu-indicator": onuInd,
766 "device-type": onuDevice.Type,
767 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700768 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800769 } else {
770 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 -0700771 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400772 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800773 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700774 /* Discovered ONUs entries need to be cleared , since after OLT
775 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530776 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800777 dh.lockDevice.Unlock()
778
Neha Sharma96b7bf22020-06-15 10:37:32 +0000779 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700780 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530781}
782
783// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530784func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400785 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000786
787 // if the connection is already available, close the previous connection (olt reboot case)
788 if dh.clientCon != nil {
789 if err = dh.clientCon.Close(); err != nil {
790 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
791 } else {
792 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
793 }
794 }
795
796 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000797 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
798 grpc.WithInsecure(),
799 grpc.WithBlock(),
800 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000801 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000802 )),
803 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000804 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000805 )))
806
807 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530808 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530809 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000810 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400811 }
812 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530813}
814
815// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530816func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400817 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530818 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400819 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530820}
821
822// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530823func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530824 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000825 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400826
827 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400828 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530829 if err != nil || device == nil {
830 /*TODO: needs to handle error scenarios */
831 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
832 }
833 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000834 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400835
836 cloned := proto.Clone(device).(*voltha.Device)
837 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
838 cloned.OperStatus = voltha.OperStatus_UNKNOWN
839 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400840
khenaidoodc2116e2021-10-19 17:33:19 -0400841 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400842 DeviceId: cloned.Id,
843 OperStatus: cloned.OperStatus,
844 ConnStatus: cloned.ConnectStatus,
845 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530846 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 -0400847 }
848
Chaitrashree G S44124192019-08-07 20:21:36 -0400849 // 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 +0530850 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400851 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530852 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400853 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400854 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
855 // all the modules initialized and ready to handle incoming ONUs.
856
Thomas Lee S985938d2020-05-04 11:40:41 +0530857 err = dh.initializeDeviceHandlerModules(ctx)
858 if err != nil {
859 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 -0400860 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400861
862 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800863 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530864 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400865 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800866 }
867 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700868
869 go startHeartbeatCheck(ctx, dh)
870
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400871 return nil
872 }
873
khenaidoo106c61a2021-08-11 18:05:46 -0400874 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400875 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400876 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400877 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400878 }
khenaidoo106c61a2021-08-11 18:05:46 -0400879 dh.populateActivePorts(ctx, ports.Items)
880 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400881 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400882 }
883
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400884 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530885 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 -0400886 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530887
cuilin20187b2a8c32019-03-26 19:52:28 -0700888 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800889 go func() {
890 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400891 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892 }
893 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000894 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000895
896 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000897 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000898 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700899
900 go startHeartbeatCheck(ctx, dh)
901
cuilin20187b2a8c32019-03-26 19:52:28 -0700902 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530903}
904
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400905func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700906 var err error
907 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400908
909 if err != nil {
910 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
911 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700912 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
913 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
Girish Gowdra9602eb42020-09-09 15:50:39 -0700914
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700915 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts)
Girish Gowdra9602eb42020-09-09 15:50:39 -0700916 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700917 var i uint32
918 for i = 0; i < dh.totalPonPorts; i++ {
919 // Instantiate resource manager
920 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 -0700921 return olterrors.ErrResourceManagerInstantiating
922 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400923 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700924 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
925 // the KV store to manage mcast group data. Provide the first instance (0th index)
926 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
927 return olterrors.ErrGroupManagerInstantiating
928 }
929 for i = 0; i < dh.totalPonPorts; i++ {
930 // Instantiate flow manager
931 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
932 return olterrors.ErrFlowManagerInstantiating
933 }
Girish Gowdra76a1b092021-07-28 10:07:04 -0700934 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700935 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400936 /* TODO: Instantiate Alarm , stats , BW managers */
937 /* Instantiating Event Manager to handle Alarms and KPIs */
938 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
939
940 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000941 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400942
943 return nil
944
945}
946
Neha Sharma96b7bf22020-06-15 10:37:32 +0000947func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400948 var err error
949 var deviceInfo *oop.DeviceInfo
950
Neha Sharma8f4e4322020-08-06 10:51:53 +0000951 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400952
953 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000954 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400955 }
956 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000957 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400958 }
959
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400961 dh.device.Root = true
962 dh.device.Vendor = deviceInfo.Vendor
963 dh.device.Model = deviceInfo.Model
964 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
965 dh.device.HardwareVersion = deviceInfo.HardwareVersion
966 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
967
968 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000969 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400970 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000971 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400972 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000973 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400974 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000975 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400976 dh.device.MacAddress = genmac
977 } else {
978 dh.device.MacAddress = deviceInfo.DeviceId
979 }
980
981 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400982 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000983 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400984 }
985
986 return deviceInfo, nil
987}
988
Neha Sharma96b7bf22020-06-15 10:37:32 +0000989func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -0700990 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530991 for {
992 select {
993 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000994 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530995 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000996 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700997
khenaidoo106c61a2021-08-11 18:05:46 -0400998 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400999 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001000 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001001 continue
1002 }
khenaidoo106c61a2021-08-11 18:05:46 -04001003 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301004 // NNI Stats
1005 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001006 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301007 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001008 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001009 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001010 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301011 }
1012 // PON Stats
1013 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001014 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301015 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1016 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001017 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001018 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301019 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001020 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001021
Girish Gowdrabcf98af2021-07-01 08:24:42 -07001022 onuGemInfoLst := dh.flowMgr[intfID].getOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001023 if len(onuGemInfoLst) > 0 {
1024 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001025 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001026 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301027 }
1028 }
1029 }
1030}
1031
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001032//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301033func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001034 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301036 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301037
1038 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001039 cgClient, err := dh.coreClient.GetCoreServiceClient()
1040 if err != nil {
1041 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1042 return
1043 }
1044
1045 // Now, set the initial PM configuration for that device
1046 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001047 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301048 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301049}
1050
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001051//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001052func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1053 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001054 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301055 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001056 HwDesc: "open_pon",
1057 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001058 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001059 },
1060 SwitchFeatures: &of.OfpSwitchFeatures{
1061 NBuffers: 256,
1062 NTables: 2,
1063 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1064 of.OfpCapabilities_OFPC_TABLE_STATS |
1065 of.OfpCapabilities_OFPC_PORT_STATS |
1066 of.OfpCapabilities_OFPC_GROUP_STATS),
1067 },
1068 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301069}
1070
khenaidoo106c61a2021-08-11 18:05:46 -04001071// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001072func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001073 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001074 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001075 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001076 }
khenaidoo106c61a2021-08-11 18:05:46 -04001077 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001078}
1079
Neha Sharma96b7bf22020-06-15 10:37:32 +00001080func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001081 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 -07001082 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001083 var deviceID string
1084 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001085 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001086
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001087 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001088 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001089 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 -07001090 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1091 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001092
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001093 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301094
1095 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1096
Neha Sharma96b7bf22020-06-15 10:37:32 +00001097 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 -07001098 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001099
khenaidoodc2116e2021-10-19 17:33:19 -04001100 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001101 ParentId: dh.device.Id,
1102 OnuId: omciInd.OnuId,
1103 ParentPortNo: ponPort,
1104 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001105 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301106 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001107 "intf-id": omciInd.IntfId,
1108 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001109 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001110 deviceType = onuDevice.Type
1111 deviceID = onuDevice.Id
1112 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001113 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001114 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001115 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001116 } else {
1117 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001118 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 +05301119 deviceType = onuInCache.(*OnuDevice).deviceType
1120 deviceID = onuInCache.(*OnuDevice).deviceID
1121 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001122 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001123 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001124
khenaidoodc2116e2021-10-19 17:33:19 -04001125 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001126 ParentDeviceId: proxyDeviceID,
1127 ChildDeviceId: deviceID,
1128 Message: omciInd.Pkt,
1129 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301130 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001131 "source": dh.openOLT.config.AdapterEndpoint,
1132 "device-type": deviceType,
1133 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001134 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001135 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001136 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001137 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301138}
1139
khenaidoo106c61a2021-08-11 18:05:46 -04001140// //ProcessInterAdapterMessage sends the proxied messages to the target device
1141// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1142// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001143// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001144// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001145// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001146// return dh.handleInterAdapterOmciMsg(ctx, msg)
1147// }
1148// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1149// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001150
khenaidoo106c61a2021-08-11 18:05:46 -04001151// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001152func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001153 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 -07001154
1155 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001156 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001157 if err != nil {
1158 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001159 "parent-device-id": dh.device.Id,
1160 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001161 }
khenaidoo106c61a2021-08-11 18:05:46 -04001162 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1163 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001164 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001165 "parent-device-id": dh.device.Id,
1166 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001167 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001168 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001169 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1170 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001171 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001172 "parent-device-id": dh.device.Id,
1173 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001174 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001175 }
1176 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301177}
1178
khenaidoodc2116e2021-10-19 17:33:19 -04001179func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001180 var intfID uint32
1181 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001182 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001183 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001184 intfID = onuDevice.ProxyAddress.GetChannelId()
1185 onuID = onuDevice.ProxyAddress.GetOnuId()
1186 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001187 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001188 intfID = omciMsg.GetProxyAddress().GetChannelId()
1189 onuID = omciMsg.GetProxyAddress().GetOnuId()
1190 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001191 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001192 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001193 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 -08001194
Thomas Lee S94109f12020-03-03 16:39:29 +05301195 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001196 "intf-id": intfID,
1197 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001198 }
1199
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001200 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1201 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001202 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001203 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1204 hex.Encode(hexPkt, omciMsg.Message)
1205 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1206
1207 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1208 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1209 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001210 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001211 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001212
Neha Sharma8f4e4322020-08-06 10:51:53 +00001213 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001214 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301215 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001216 "intf-id": intfID,
1217 "onu-id": onuID,
1218 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001219 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001220 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001221}
1222
David K. Bainbridge794735f2020-02-11 21:01:37 -08001223func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301224 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})
Girish Gowdra197acc12021-08-16 10:59:45 -07001225 if err := dh.flowMgr[intfID].AddOnuInfoToFlowMgrCacheAndKvStore(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001226 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001227 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001228 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301229 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301230 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001231 st, _ := status.FromError(err)
1232 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001233 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1234
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001235 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301236 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001237 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001238 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001239 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001240 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001241 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001242}
1243
Mahir Gunyelb0046752021-02-26 13:51:05 -08001244func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001245 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001246 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001247
Mahir Gunyelb0046752021-02-26 13:51:05 -08001248 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001249 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301250
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301251 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001252 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001253 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301254
1255 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1256 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1257 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1258 OnuLosRaise event sent for it */
1259 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1260 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1261 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001262 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301263 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1264 "currentIntfId": onuDiscInd.GetIntfId()})
1265 // TODO:: Should we need to ignore raising OnuLosClear event
1266 // when onu connected to different PON?
1267 }
1268 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1269 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1270 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001271 go func() {
1272 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001273 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001274 }
1275 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301276 }
1277 return true
1278 })
1279
Neha Sharma96b7bf22020-06-15 10:37:32 +00001280 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001282 }
1283
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001284 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001285
1286 // check the ONU is already know to the OLT
1287 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001288 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001289 ParentId: dh.device.Id,
1290 SerialNumber: sn,
1291 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001292
1293 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001294 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 -08001295 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001296 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 -08001297 switch e.Code() {
1298 case codes.Internal:
1299 // this probably means NOT FOUND, so just create a new device
1300 onuDevice = nil
1301 case codes.DeadlineExceeded:
1302 // if the call times out, cleanup and exit
1303 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001304 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001305 }
1306 }
1307 }
1308
1309 if onuDevice == nil {
1310 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001311 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001312 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001313 ponintfid := onuDiscInd.GetIntfId()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001314 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001315
Neha Sharma96b7bf22020-06-15 10:37:32 +00001316 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001317
1318 if err != nil {
1319 // if we can't create an ID in resource manager,
1320 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001321 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001322 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001323 "pon-intf-id": ponintfid,
1324 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001325 }
1326
khenaidoodc2116e2021-10-19 17:33:19 -04001327 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001328 ParentId: dh.device.Id,
1329 ParentPortNo: parentPortNo,
1330 ChannelId: channelID,
1331 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1332 SerialNumber: sn,
1333 OnuId: onuID,
1334 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001335 dh.discOnus.Delete(sn)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001336 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 +05301337 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001338 "pon-intf-id": ponintfid,
1339 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001340 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001341 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 -07001342 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001343 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001344 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301345 log.Fields{"onuDevice": onuDevice,
1346 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001347 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301348 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001349 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001350
khenaidoo106c61a2021-08-11 18:05:46 -04001351 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1352 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1353 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1354 cancel()
1355 if err != nil {
1356 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1357 }
1358
Matteo Scandolo945e4012019-12-12 14:16:11 -08001359 // we can now use the existing ONU Id
1360 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001361 //Insert the ONU into cache to use in OnuIndication.
1362 //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 +00001363 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001364 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301365 "intfId": onuDiscInd.GetIntfId(),
1366 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001367 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001368
khenaidoo106c61a2021-08-11 18:05:46 -04001369 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301370 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001371 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301372 log.Fields{"onu": onuDev,
1373 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001374
khenaidoodc2116e2021-10-19 17:33:19 -04001375 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001376 DeviceId: onuDevice.Id,
1377 ParentDeviceId: dh.device.Id,
1378 OperStatus: common.OperStatus_DISCOVERED,
1379 ConnStatus: common.ConnectStatus_REACHABLE,
1380 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301381 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001382 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001383 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001384 }
khenaidoo106c61a2021-08-11 18:05:46 -04001385
Neha Sharma96b7bf22020-06-15 10:37:32 +00001386 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001387 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301388 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001389 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001390 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001391 }
1392 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001393}
1394
Mahir Gunyelb0046752021-02-26 13:51:05 -08001395func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001396
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001397 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001398 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001399 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001400 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001401 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301402 log.Fields{"onuId": onuInd.OnuId,
1403 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301404 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001405 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001406 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301407
David K. Bainbridge794735f2020-02-11 21:01:37 -08001408 errFields := log.Fields{"device-id": dh.device.Id}
1409
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301410 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1411
Mahir Gunyele77977b2019-06-27 05:36:22 -07001412 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1413 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001415 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001416 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001417 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1418 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001419 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001420 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001421 errFields["onu-id"] = onuInd.OnuId
1422 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001423 }
khenaidoodc2116e2021-10-19 17:33:19 -04001424 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001425 ParentId: dh.device.Id,
1426 SerialNumber: serialNumber,
1427 OnuId: onuInd.OnuId,
1428 ParentPortNo: ponPort,
1429 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001430 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001431
David K. Bainbridge794735f2020-02-11 21:01:37 -08001432 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001433 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001434 }
1435
David K. Bainbridge794735f2020-02-11 21:01:37 -08001436 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001437 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001438 "previousIntfId": onuDevice.ParentPortNo,
1439 "currentIntfId": ponPort})
1440 }
1441
1442 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001443 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301444 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1445 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301446 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001447 }
1448 if !foundInCache {
1449 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1450
khenaidoo106c61a2021-08-11 18:05:46 -04001451 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 -08001452
1453 }
kesavand7cf3a052020-08-28 12:49:18 +05301454 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001455 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001456 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301457 }
1458 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001459 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001460 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001461 }
1462 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001463}
1464
Neha Sharma96b7bf22020-06-15 10:37:32 +00001465func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001466 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 -07001467 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1468 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1469 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1470 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001471 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001472 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1473 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001474 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001475 onuInd.OperState = "down"
1476 }
1477 }
1478
David K. Bainbridge794735f2020-02-11 21:01:37 -08001479 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001480 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001481 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 -04001482
khenaidoodc2116e2021-10-19 17:33:19 -04001483 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001484 DeviceId: onuDevice.Id,
1485 OnuIndication: onuInd,
1486 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001487 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301488 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001489 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001490 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001491 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001492 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001493 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001494 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001495 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001496 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001497 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001498}
1499
cuilin20187b2a8c32019-03-26 19:52:28 -07001500func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1501 if serialNum != nil {
1502 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001503 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001504 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001505}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001506func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1507 decodedStr, err := hex.DecodeString(serialNum[4:])
1508 if err != nil {
1509 return nil, err
1510 }
1511 return &oop.SerialNumber{
1512 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001513 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001514 }, nil
1515}
cuilin20187b2a8c32019-03-26 19:52:28 -07001516
1517func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001518 if len(vendorSpecific) > 3 {
1519 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1520 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1521 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1522 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1523 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1524 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1525 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1526 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1527 return tmp
1528 }
1529 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001530}
1531
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001532//UpdateFlowsBulk upates the bulk flow
1533func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301534 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001535}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001536
1537//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001538func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1539 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301540 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001541 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301542 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001543
khenaidoodc2116e2021-10-19 17:33:19 -04001544 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001545 ParentId: dh.device.Id,
1546 OnuId: onuID,
1547 ParentPortNo: parentPort,
1548 })
1549
Girish Gowdru0c588b22019-04-23 23:24:56 -04001550 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001551 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001552 "intf-id": parentPort,
1553 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001554 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001555 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 -08001556 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301557}
1558
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001559// SendPacketInToCore sends packet-in to core
1560// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1561// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001562func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001563 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001564 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001565 "port": logicalPort,
1566 "packet": hex.EncodeToString(packetPayload),
1567 "device-id": dh.device.Id,
1568 })
1569 }
khenaidoo106c61a2021-08-11 18:05:46 -04001570
khenaidoodc2116e2021-10-19 17:33:19 -04001571 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001572 DeviceId: dh.device.Id,
1573 Port: logicalPort,
1574 Packet: packetPayload,
1575 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301576 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001577 "source": "adapter",
1578 "destination": "core",
1579 "device-id": dh.device.Id,
1580 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001581 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001582 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001583 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001584 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001585 "packet": hex.EncodeToString(packetPayload),
1586 "device-id": dh.device.Id,
1587 })
1588 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001589 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001590}
1591
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001592// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001593func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001595
1596 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1597 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001599 }
1600
Kent Hagermane6ff1012020-07-14 15:07:53 -04001601 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001602 metrics := dh.metrics.GetSubscriberMetrics()
1603 for _, m := range pmConfigs.Metrics {
1604 metrics[m.Name].Enabled = m.Enabled
1605
1606 }
1607 }
1608}
1609
khenaidoodc2116e2021-10-19 17:33:19 -04001610func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001611 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001612 var errorsList []error
1613
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001614 if dh.getDeviceDeletionInProgressFlag() {
1615 // The device itself is going to be reset as part of deletion. So nothing to be done.
1616 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1617 return nil
1618 }
1619
Girish Gowdru0c588b22019-04-23 23:24:56 -04001620 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001621 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001622 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001623
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301625 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001626 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301627 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001628 if flow_utils.HasGroup(flow) {
1629 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1630 } else {
1631 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1632 }
Girish Gowdracefae192020-03-19 18:14:10 -07001633 if err != nil {
1634 errorsList = append(errorsList, err)
1635 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001636 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301637
1638 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001639 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001640 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301641 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001642 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301643 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001644 if flow_utils.HasGroup(flow) {
1645 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1646 } else {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001647 if dh.flowMgr == nil || dh.flowMgr[ponIf] == nil {
1648 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1649 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1650 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1651 } else {
1652 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1653 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001654 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001655 if err != nil {
1656 errorsList = append(errorsList, err)
1657 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301658 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001659 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001660
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001661 return errorsList
1662}
1663
1664func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1665 var err error
1666 var errorsList []error
1667
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001668 if dh.getDeviceDeletionInProgressFlag() {
1669 // The device itself is going to be reset as part of deletion. So nothing to be done.
1670 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1671 return nil
1672 }
1673
Girish Gowdracefae192020-03-19 18:14:10 -07001674 // 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 +00001675 if groups != nil {
1676 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001677 // err = dh.groupMgr.AddGroup(ctx, group)
1678 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001679 if err != nil {
1680 errorsList = append(errorsList, err)
1681 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001682 }
1683 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001684 // err = dh.groupMgr.ModifyGroup(ctx, group)
1685 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001686 if err != nil {
1687 errorsList = append(errorsList, err)
1688 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001689 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001690 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001691 // err = dh.groupMgr.DeleteGroup(ctx, group)
1692 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001693 if err != nil {
1694 errorsList = append(errorsList, err)
1695 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001696 }
1697 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001698
1699 return errorsList
1700}
1701
1702//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001703func (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 -07001704
1705 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001706
1707 if dh.getDeviceDeletionInProgressFlag() {
1708 // The device itself is going to be reset as part of deletion. So nothing to be done.
1709 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1710 return nil
1711 }
1712
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001713 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1714 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1715 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001716 if len(errorsList) > 0 {
1717 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1718 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001719 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001720 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301721}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001722
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001723//DisableDevice disables the given device
1724//It marks the following for the given device:
1725//Device-Handler Admin-State : down
1726//Device Port-State: UNKNOWN
1727//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001728func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001729 /* On device disable ,admin state update has to be done prior sending request to agent since
1730 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001731 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001732 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001733 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001734 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001735 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001736 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001737 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001738 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001739 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001740 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301741
1742 dh.discOnus = sync.Map{}
1743 dh.onus = sync.Map{}
1744
Thomas Lee S85f37312020-04-03 17:06:12 +05301745 //stopping the stats collector
1746 dh.stopCollector <- true
1747
Neha Sharma96b7bf22020-06-15 10:37:32 +00001748 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001749 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301750 //Update device Admin state
1751 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001752
kdarapu1afeceb2020-02-12 01:38:09 -05001753 // 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 -04001754 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001755 DeviceId: cloned.Id,
1756 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
1757 OperStatus: voltha.OperStatus_UNKNOWN,
1758 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001759 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001760 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001761 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001762 return nil
1763}
1764
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001766 // Update onu state as unreachable in onu adapter
1767 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301768 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04001769
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001770 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001771 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001772 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001773 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 -04001774 }
1775 if onuDevices != nil {
1776 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04001777 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001778 DeviceId: onuDevice.Id,
1779 OnuIndication: &onuInd,
1780 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001781 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001782 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001783 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001784 }
1785
1786 }
1787 }
1788
1789}
1790
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001791//ReenableDevice re-enables the olt device after disable
1792//It marks the following for the given device:
1793//Device-Handler Admin-State : up
1794//Device Port-State: ACTIVE
1795//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001796func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001797 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301798 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001799 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301800 }
1801 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001803
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001804 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04001805 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001806 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001807 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001808 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
1809 } else {
1810 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1811 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
1812 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001813 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001814 if retError == nil {
1815 //Update the device oper status as ACTIVE
1816 device.OperStatus = voltha.OperStatus_ACTIVE
1817 } else {
1818 //Update the device oper status as FAILED
1819 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001820 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001821 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001822
khenaidoodc2116e2021-10-19 17:33:19 -04001823 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001824 DeviceId: device.Id,
1825 OperStatus: device.OperStatus,
1826 ConnStatus: device.ConnectStatus,
1827 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301828 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001829 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001830 "connect-status": device.ConnectStatus,
1831 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001832 }
kesavand39e0aa32020-01-28 20:58:50 -05001833
Neha Sharma96b7bf22020-06-15 10:37:32 +00001834 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001835
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001836 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001837}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001838
npujarec5762e2020-01-01 14:08:48 +05301839func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001840 var uniID uint32
1841 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301842 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001843 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001844 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001845 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001846 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001847 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001848 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001850 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001851 for _, tpID := range tpIDList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001852 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001853 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001854 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001855 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001856 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001857 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001858 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001859 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301860 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001861 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1862 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001863 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301864 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001865 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001866 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001867 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 +00001868 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001869 }
1870 return nil
1871}
1872
Devmalya Paul495b94a2019-08-27 19:42:00 -04001873// 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 +05301874func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001875 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001876 /* Clear the KV store data associated with the all the UNI ports
1877 This clears up flow data and also resource map data for various
1878 other pon resources like alloc_id and gemport_id
1879 */
Girish Gowdra950326e2021-11-05 12:43:24 -07001880
1881 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001882 var wg sync.WaitGroup
1883 wg.Add(1) // for the mcast routine below to finish
1884 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
1885 for _, flMgr := range dh.flowMgr {
1886 wg.Add(1) // for the flow handler routine below to finish
1887 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
1888 }
1889 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
1890 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
1891 } else {
1892 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
1893 }
Girish Gowdra950326e2021-11-05 12:43:24 -07001894
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001895 dh.cleanupDeviceResources(ctx)
1896 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 -04001897 // Stop the Stats collector
1898 dh.stopCollector <- true
1899 // stop the heartbeat check routine
1900 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301901 dh.lockDevice.RLock()
1902 // Stop the read indication only if it the routine is active
1903 if dh.isReadIndicationRoutineActive {
1904 dh.stopIndications <- true
1905 }
1906 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001907 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001908 //Reset the state
1909 if dh.Client != nil {
1910 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301911 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001912 }
1913 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07001914 // There is no need to update the core about operation status and connection status of the OLT.
1915 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1916 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1917 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001918
khenaidoo7eb2d672021-10-22 19:08:50 -04001919 // Stop the adapter grpc clients for that parent device
1920 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001921 return nil
1922}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001923func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001924
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001925 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301926 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001927 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001928 var err error
Girish Gowdrabcf98af2021-07-01 08:24:42 -07001929 onuGemData := dh.flowMgr[ponPort].getOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03001930 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001931 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03001932 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001933 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301934 }
1935 }
Girish Gowdra950326e2021-11-05 12:43:24 -07001936 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx, ponPort)
1937 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx, ponPort)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001938 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
1939 logger.Debug(ctx, err)
1940 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001941 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001942 }
A R Karthick1f85b802019-10-11 05:06:05 +00001943
Devmalya Paul495b94a2019-08-27 19:42:00 -04001944 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301945 dh.onus.Range(func(key interface{}, value interface{}) bool {
1946 dh.onus.Delete(key)
1947 return true
1948 })
1949
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001950 /*Delete discovered ONU map for the device*/
1951 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1952 dh.discOnus.Delete(key)
1953 return true
1954 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001955}
1956
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001957//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001958func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001959 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301960 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001961 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001962 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001963 return nil
1964}
1965
David K. Bainbridge794735f2020-02-11 21:01:37 -08001966func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001967 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001968 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001969 "packet-indication": *packetIn,
1970 "device-id": dh.device.Id,
1971 "packet": hex.EncodeToString(packetIn.Pkt),
1972 })
1973 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001974 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001975 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001976 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001977 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001978 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001979 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001980 "logical-port-num": logicalPortNum,
1981 "device-id": dh.device.Id,
1982 "packet": hex.EncodeToString(packetIn.Pkt),
1983 })
1984 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001985
khenaidoodc2116e2021-10-19 17:33:19 -04001986 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001987 DeviceId: dh.device.Id,
1988 Port: logicalPortNum,
1989 Packet: packetIn.Pkt,
1990 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301991 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001992 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301993 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001994 "device-id": dh.device.Id,
1995 "packet": hex.EncodeToString(packetIn.Pkt),
1996 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001997 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001998
Matteo Scandolo92186242020-06-12 10:54:18 -07001999 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002000 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002001 "packet": hex.EncodeToString(packetIn.Pkt),
2002 "device-id": dh.device.Id,
2003 })
2004 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002005 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002006}
2007
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002008// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002009func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002010 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002011 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002012 "device-id": dh.device.Id,
2013 "egress-port-no": egressPortNo,
2014 "pkt-length": len(packet.Data),
2015 "packet": hex.EncodeToString(packet.Data),
2016 })
2017 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002018
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002019 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002020 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002021 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2022 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302023 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2024 // Do not packet-out lldp packets on uni port.
2025 // ONOS has no clue about uni/nni ports, it just packets out on all
2026 // available ports on the Logical Switch. It should not be interested
2027 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002028 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002029 "device-id": dh.device.Id,
2030 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302031 return nil
2032 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002033 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2034 if innerEthType == 0x8100 {
2035 // q-in-q 802.1ad or 802.1q double tagged packet.
2036 // slice out the outer tag.
2037 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002038 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002039 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002040 "packet-data": hex.EncodeToString(packet.Data),
2041 "device-id": dh.device.Id,
2042 })
2043 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002044 }
2045 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002046 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2047 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2048 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002049
Girish Gowdra9602eb42020-09-09 15:50:39 -07002050 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002051 if err != nil {
2052 // In this case the openolt agent will receive the gemPortID as 0.
2053 // The agent tries to retrieve the gemPortID in this case.
2054 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002055 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002056 "intf-id": intfID,
2057 "onu-id": onuID,
2058 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002059 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302060 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002061 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002062 }
2063
2064 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002065 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002066 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002067 "egress-port-no": egressPortNo,
2068 "intf-id": intfID,
2069 "onu-id": onuID,
2070 "uni-id": uniID,
2071 "gem-port-id": gemPortID,
2072 "packet": hex.EncodeToString(packet.Data),
2073 "device-id": dh.device.Id,
2074 })
2075 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002076
npujarec5762e2020-01-01 14:08:48 +05302077 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302078 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002079 "source": "adapter",
2080 "destination": "onu",
2081 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002082 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002083 "oni-id": onuID,
2084 "uni-id": uniID,
2085 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002086 "packet": hex.EncodeToString(packet.Data),
2087 "device-id": dh.device.Id,
2088 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002089 }
2090 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002091 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002092 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002093 return olterrors.NewErrInvalidValue(log.Fields{
2094 "egress-nni-port": egressPortNo,
2095 "device-id": dh.device.Id,
2096 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002097 }
2098 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002099
Matteo Scandolo92186242020-06-12 10:54:18 -07002100 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002101 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002102 "uplink-pkt": uplinkPkt,
2103 "packet": hex.EncodeToString(packet.Data),
2104 "device-id": dh.device.Id,
2105 })
2106 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002107
npujarec5762e2020-01-01 14:08:48 +05302108 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002109 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2110 "packet": hex.EncodeToString(packet.Data),
2111 "device-id": dh.device.Id,
2112 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002113 }
2114 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002115 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302116 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002117 "egressPortType": egressPortType,
2118 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302119 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002120 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002121 }
2122 return nil
2123}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002124
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002125func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2126 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002127}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302128
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002129func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002130
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302131 // start the heartbeat check towards the OLT.
2132 var timerCheck *time.Timer
2133
2134 for {
2135 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2136 select {
2137 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002138 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002139 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002140 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302141 if timerCheck == nil {
2142 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002143 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302144 }
2145 } else {
2146 if timerCheck != nil {
2147 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002148 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302149 }
2150 timerCheck = nil
2151 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002152 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302153 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302154 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302155 }
2156 cancel()
2157 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002158 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302159 return
2160 }
2161 }
2162}
2163
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002164func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002165 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002166 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002167 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2168 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2169 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2170 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2171 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002172 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002173 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2174 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002175 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302176
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002177 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2178 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002179 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002180 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002181 DeviceId: dh.device.Id,
2182 OperStatus: voltha.OperStatus_UNKNOWN,
2183 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2184 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002185 _ = 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 -04002186 }
khenaidoo106c61a2021-08-11 18:05:46 -04002187
khenaidoodc2116e2021-10-19 17:33:19 -04002188 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002189 DeviceId: dh.device.Id,
2190 PortTypeFilter: 0,
2191 OperStatus: voltha.OperStatus_UNKNOWN,
2192 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002193 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002194 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002195
2196 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002197 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002198 cloned := proto.Clone(device).(*voltha.Device)
2199 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2200 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2201 dh.device = cloned // update local copy of the device
2202 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002203
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002204 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002205 // Stop the Stats collector
2206 dh.stopCollector <- true
2207 // stop the heartbeat check routine
2208 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002209
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002210 dh.lockDevice.RLock()
2211 // Stop the read indication only if it the routine is active
2212 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2213 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2214 // on next execution of the readIndication routine.
2215 if dh.isReadIndicationRoutineActive {
2216 dh.stopIndications <- true
2217 }
2218 dh.lockDevice.RUnlock()
2219
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002220 var wg sync.WaitGroup
2221 wg.Add(1) // for the multicast handler routine
2222 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002223 for _, flMgr := range dh.flowMgr {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002224 wg.Add(1) // for the flow handler routine
2225 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2226 }
2227 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2228 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2229 } else {
2230 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002231 }
2232
Gamze Abakac2c32a62021-03-11 11:44:18 +00002233 //reset adapter reconcile flag
2234 dh.adapterPreviouslyConnected = false
2235
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002236 dh.transitionMap.Handle(ctx, DeviceInit)
2237
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302238 }
2239}
kesavand39e0aa32020-01-28 20:58:50 -05002240
2241// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002242func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2243 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2244 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002245}
2246
2247// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002248func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2249 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2250 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002251}
2252
kdarapu1afeceb2020-02-12 01:38:09 -05002253//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 +00002254func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2255 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002256 if port.GetType() == voltha.Port_ETHERNET_NNI {
2257 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002258 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302259 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302260 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002261 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002262 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002263 }
2264 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002265 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002266 ponIntf := &oop.Interface{IntfId: ponID}
2267 var operStatus voltha.OperStatus_Types
2268 if enablePort {
2269 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302270 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002271
2272 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302273 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002274 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002275 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002276 }
2277 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002278 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002279 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002280 } else {
2281 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302282 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002283 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302284 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002285 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002286 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002287 }
2288 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002289 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002290 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002291 }
khenaidoodc2116e2021-10-19 17:33:19 -04002292 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002293 DeviceId: dh.device.Id,
2294 PortType: voltha.Port_PON_OLT,
2295 PortNo: port.PortNo,
2296 OperStatus: operStatus,
2297 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302298 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302299 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002300 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002301 }
2302 return nil
2303}
2304
kdarapu1afeceb2020-02-12 01:38:09 -05002305//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002306func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002307 // Disable the port and update the oper_port_status to core
2308 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002309 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002310 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002311 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302312 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302313 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002314 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002315 }
2316 }
2317 }
2318 return nil
2319}
2320
2321//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002322func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2323 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2324 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002325 if port.Type == voltha.Port_ETHERNET_NNI {
2326 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002327 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002328 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002329 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002330 }
2331 }
2332 if port.Type == voltha.Port_PON_OLT {
2333 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002334 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002335 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002336 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002337 }
2338 }
2339 }
2340}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002341
2342// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002343func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002344 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002345 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002346 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002347
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002348 var sn *oop.SerialNumber
2349 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002350 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302351 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002352 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302353 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002354 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002355 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002356
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002357 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002358 //clear PON resources associated with ONU
2359 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, intfID, onuID)
2360 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2361 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2362 "device-id": dh.device.Id,
2363 "intf-id": intfID,
2364 "onuID": onuID,
2365 "err": err})
2366 } else {
2367 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
2368 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2369 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2370 "device-id": dh.device.Id,
2371 "onu-device": onu,
2372 "err": err})
2373 }
2374 // Clear flowids for gem cache.
2375 for _, gem := range onuGem.GemPorts {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002376 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, intfID, gem)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002377 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002378 if err := dh.flowMgr[intfID].RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx, intfID, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002379 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2380 "intf-id": intfID,
2381 "onu-device": onu,
2382 "onu-gem": onuGem,
2383 "err": err})
2384 //Not returning error on cleanup.
2385 }
2386 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302387
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002388 }
Himani Chawlabcc95852021-10-27 10:55:40 +05302389 dh.resourceMgr[intfID].FreeonuID(ctx, intfID, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002390 dh.onus.Delete(onuKey)
2391 dh.discOnus.Delete(onuSn)
2392
2393 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002394 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302395 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302396 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002397 "onu-id": onuID}, err).Log()
2398 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002399
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002400 return nil
2401}
Girish Gowdracefae192020-03-19 18:14:10 -07002402
2403func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002404 for _, field := range flow_utils.GetOfbFields(flow) {
2405 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002406 return field.GetPort()
2407 }
2408 }
2409 return InvalidPort
2410}
2411
2412func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002413 for _, action := range flow_utils.GetActions(flow) {
2414 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002415 if out := action.GetOutput(); out != nil {
2416 return out.GetPort()
2417 }
2418 }
2419 }
2420 return InvalidPort
2421}
2422
Girish Gowdracefae192020-03-19 18:14:10 -07002423func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2424 inPort := getInPortFromFlow(flow)
2425 outPort := getOutPortFromFlow(flow)
2426
2427 if inPort == InvalidPort || outPort == InvalidPort {
2428 return inPort, outPort
2429 }
2430
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002431 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002432 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002433 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002434 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002435 return uniPort, outPort
2436 }
2437 }
2438 } else {
2439 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002440 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002441 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002442 return inPort, uniPort
2443 }
2444 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002445 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002446 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002447 return uniPort, outPort
2448 }
2449 }
2450 }
2451
2452 return InvalidPort, InvalidPort
2453}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002454
2455func extractOmciTransactionID(omciPkt []byte) uint16 {
2456 if len(omciPkt) > 3 {
2457 d := omciPkt[0:2]
2458 transid := binary.BigEndian.Uint16(d)
2459 return transid
2460 }
2461 return 0
2462}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002463
2464// StoreOnuDevice stores the onu parameters to the local cache.
2465func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2466 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2467 dh.onus.Store(onuKey, onuDevice)
2468}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002469
khenaidoodc2116e2021-10-19 17:33:19 -04002470func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002471 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002472 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002473 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002474 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002475 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002476 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002477 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002478 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2479 return nil, err
2480 }
2481 ID = device.ProxyAddress.GetOnuId()
2482 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2483 valueparam.Onu = &Onu
2484 valueparam.Value = value
2485
2486 // This API is unsupported until agent patch is added
2487 resp.Unsupported = uint32(value)
2488 _ = ctx
2489
2490 // Uncomment this code once agent changes are complete and tests
2491 /*
2492 resp, err = dh.Client.GetValue(ctx, valueparam)
2493 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002494 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002495 return nil, err
2496 }
2497 */
2498
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002499 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 -08002500 return resp, nil
2501}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002502
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002503func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002504 // Default to PON0
2505 var intfID uint32
2506 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002507 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002508 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002509 }
2510 return intfID
2511}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002512
Mahir Gunyelb0046752021-02-26 13:51:05 -08002513func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2514 dh.perPonOnuIndicationChannelLock.Lock()
2515 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2516 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002517 return ch.indicationChannel
2518 }
2519 channels := onuIndicationChannels{
2520 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002521 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002522 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002523 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002524 stopChannel: make(chan struct{}),
2525 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002526 dh.perPonOnuIndicationChannel[intfID] = channels
2527 dh.perPonOnuIndicationChannelLock.Unlock()
2528 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002529 return channels.indicationChannel
2530
2531}
2532
Mahir Gunyelb0046752021-02-26 13:51:05 -08002533func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2534 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2535 dh.perPonOnuIndicationChannelLock.Lock()
2536 defer dh.perPonOnuIndicationChannelLock.Unlock()
2537 for _, v := range dh.perPonOnuIndicationChannel {
2538 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002539 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002540 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002541}
2542
Mahir Gunyelb0046752021-02-26 13:51:05 -08002543func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2544 ind := onuIndicationMsg{
2545 ctx: ctx,
2546 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002547 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002548 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002549 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002550 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002551}
2552
Mahir Gunyelb0046752021-02-26 13:51:05 -08002553func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002554 for {
2555 select {
2556 // process one indication per onu, before proceeding to the next one
2557 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08002558 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002559 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08002560 "ind": indication})
2561 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002562 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002563 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002564 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2565 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002566 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002567 }
2568 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002569 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002570 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2571 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002572 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002573 }
2574 }
2575 case <-onuChannels.stopChannel:
2576 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2577 close(onuChannels.indicationChannel)
2578 return
2579 }
2580 }
2581}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002582
2583// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2584// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04002585func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002586 if dh.getDeviceDeletionInProgressFlag() {
2587 // The device itself is going to be reset as part of deletion. So nothing to be done.
2588 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2589 return nil
2590 }
2591
Girish Gowdra491a9c62021-01-06 16:43:07 -08002592 // Step1 : Fill McastFlowOrGroupControlBlock
2593 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2594 // Step3 : Wait on response channel for response
2595 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002596 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002597 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2598 errChan := make(chan error)
2599 var groupID uint32
2600 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2601 ctx: ctx,
2602 flowOrGroupAction: action,
2603 flow: flow,
2604 group: group,
2605 errChan: &errChan,
2606 }
2607 if flow != nil {
2608 groupID = flow_utils.GetGroup(flow)
2609 } else if group != nil {
2610 groupID = group.Desc.GroupId
2611 } else {
2612 return errors.New("flow-and-group-both-nil")
2613 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002614 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2615 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2616 // Derive the appropriate go routine to handle the request by a simple module operation.
2617 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2618 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2619 // Wait for handler to return error value
2620 err := <-errChan
2621 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2622 return err
2623 }
2624 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2625 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002626}
2627
2628// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002629func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002630 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002631 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002632 // block on the channel to receive an incoming mcast flow/group
2633 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002634 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2635 if mcastFlowOrGroupCb.flow != nil {
2636 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2637 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2638 log.Fields{"device-id": dh.device.Id,
2639 "flowToAdd": mcastFlowOrGroupCb.flow})
2640 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2641 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2642 // Pass the return value over the return channel
2643 *mcastFlowOrGroupCb.errChan <- err
2644 } else { // flow remove
2645 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2646 log.Fields{"device-id": dh.device.Id,
2647 "flowToRemove": mcastFlowOrGroupCb.flow})
2648 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2649 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2650 // Pass the return value over the return channel
2651 *mcastFlowOrGroupCb.errChan <- err
2652 }
2653 } else { // mcast group
2654 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2655 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2656 log.Fields{"device-id": dh.device.Id,
2657 "groupToAdd": mcastFlowOrGroupCb.group})
2658 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2659 // Pass the return value over the return channel
2660 *mcastFlowOrGroupCb.errChan <- err
2661 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2662 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2663 log.Fields{"device-id": dh.device.Id,
2664 "groupToModify": mcastFlowOrGroupCb.group})
2665 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2666 // Pass the return value over the return channel
2667 *mcastFlowOrGroupCb.errChan <- err
2668 } else { // group remove
2669 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2670 log.Fields{"device-id": dh.device.Id,
2671 "groupToRemove": mcastFlowOrGroupCb.group})
2672 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2673 // Pass the return value over the return channel
2674 *mcastFlowOrGroupCb.errChan <- err
2675 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002676 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002677 case <-stopHandler:
2678 dh.mcastHandlerRoutineActive[routineIndex] = false
2679 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08002680 }
2681 }
2682}
kesavand62126212021-01-12 04:56:06 -05002683
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002684// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002685func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002686 for i, v := range dh.stopMcastHandlerRoutine {
2687 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002688 select {
2689 case v <- true:
2690 case <-time.After(time.Second * 5):
2691 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
2692 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002693 }
2694 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002695 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002696 logger.Debug(ctx, "stopped all mcast handler routines")
2697}
2698
kesavand62126212021-01-12 04:56:06 -05002699func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2700
2701 singleValResp := extension.SingleGetValueResponse{
2702 Response: &extension.GetValueResponse{
2703 Response: &extension.GetValueResponse_PortCoutners{
2704 PortCoutners: &extension.GetOltPortCountersResponse{},
2705 },
2706 },
2707 }
2708
2709 errResp := func(status extension.GetValueResponse_Status,
2710 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2711 return &extension.SingleGetValueResponse{
2712 Response: &extension.GetValueResponse{
2713 Status: status,
2714 ErrReason: reason,
2715 },
2716 }
2717 }
2718
2719 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2720 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2721 //send error response
2722 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2723 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2724 }
2725 statIndChn := make(chan bool, 1)
2726 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2727 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2728 //request openOlt agent to send the the port statistics indication
2729
2730 go func() {
2731 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2732 if err != nil {
2733 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2734 }
2735 }()
2736 select {
2737 case <-statIndChn:
2738 //indication received for ports stats
2739 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2740 case <-time.After(oltPortInfoTimeout * time.Second):
2741 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2742 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2743 case <-ctx.Done():
2744 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2745 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2746 }
2747 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2748 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002749 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05002750 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2751 cmnni := dh.portStats.collectNNIMetrics(intfID)
2752 if cmnni == nil {
2753 //TODO define the error reason
2754 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2755 }
2756 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2757 return &singleValResp
2758
2759 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2760 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002761 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05002762 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2763 cmpon := dh.portStats.collectPONMetrics(intfID)
2764 if cmpon == nil {
2765 //TODO define the error reason
2766 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2767 }
2768 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2769 return &singleValResp
2770 }
2771 }
2772 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2773}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302774
2775func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2776
2777 singleValResp := extension.SingleGetValueResponse{
2778 Response: &extension.GetValueResponse{
2779 Response: &extension.GetValueResponse_OnuPonCounters{
2780 OnuPonCounters: &extension.GetOnuCountersResponse{},
2781 },
2782 },
2783 }
2784
2785 errResp := func(status extension.GetValueResponse_Status,
2786 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2787 return &extension.SingleGetValueResponse{
2788 Response: &extension.GetValueResponse{
2789 Status: status,
2790 ErrReason: reason,
2791 },
2792 }
2793 }
2794 intfID := onuPonInfo.IntfId
2795 onuID := onuPonInfo.OnuId
2796 onuKey := dh.formOnuKey(intfID, onuID)
2797
2798 if _, ok := dh.onus.Load(onuKey); !ok {
2799 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2800 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2801 }
2802 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2803 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2804 if cmnni == nil {
2805 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2806 }
2807 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2808 return &singleValResp
2809
2810}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002811
2812func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2813
2814 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
2815 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
2816 if err != nil {
2817 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
2818 return generateSingleGetValueErrorResponse(err)
2819 }
2820 return &extension.SingleGetValueResponse{
2821 Response: &extension.GetValueResponse{
2822 Status: extension.GetValueResponse_OK,
2823 Response: &extension.GetValueResponse_RxPower{
2824 RxPower: &extension.GetRxPowerResponse{
2825 IntfId: rxPowerRequest.IntfId,
2826 OnuId: rxPowerRequest.OnuId,
2827 Status: rxPower.Status,
2828 FailReason: rxPower.FailReason.String(),
2829 RxPower: rxPower.RxPowerMeanDbm,
2830 },
2831 },
2832 },
2833 }
2834}
2835
2836func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
2837 errResp := func(status extension.GetValueResponse_Status,
2838 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2839 return &extension.SingleGetValueResponse{
2840 Response: &extension.GetValueResponse{
2841 Status: status,
2842 ErrReason: reason,
2843 },
2844 }
2845 }
2846
2847 if err != nil {
2848 if e, ok := status.FromError(err); ok {
2849 switch e.Code() {
2850 case codes.Internal:
2851 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2852 case codes.DeadlineExceeded:
2853 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2854 case codes.Unimplemented:
2855 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
2856 case codes.NotFound:
2857 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2858 }
2859 }
2860 }
2861
2862 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
2863}
khenaidoo106c61a2021-08-11 18:05:46 -04002864
2865/*
2866Helper functions to communicate with Core
2867*/
2868
2869func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
2870 cClient, err := dh.coreClient.GetCoreServiceClient()
2871 if err != nil || cClient == nil {
2872 return nil, err
2873 }
2874 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2875 defer cancel()
2876 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
2877}
2878
khenaidoodc2116e2021-10-19 17:33:19 -04002879func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002880 cClient, err := dh.coreClient.GetCoreServiceClient()
2881 if err != nil || cClient == nil {
2882 return nil, err
2883 }
2884 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2885 defer cancel()
2886 return cClient.GetChildDevice(subCtx, childDeviceFilter)
2887}
2888
khenaidoodc2116e2021-10-19 17:33:19 -04002889func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002890 cClient, err := dh.coreClient.GetCoreServiceClient()
2891 if err != nil || cClient == nil {
2892 return err
2893 }
2894 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2895 defer cancel()
2896 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
2897 return err
2898}
2899
2900func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
2901 cClient, err := dh.coreClient.GetCoreServiceClient()
2902 if err != nil || cClient == nil {
2903 return nil, err
2904 }
2905 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2906 defer cancel()
2907 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
2908}
2909
2910func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
2911 cClient, err := dh.coreClient.GetCoreServiceClient()
2912 if err != nil || cClient == nil {
2913 return nil, err
2914 }
2915 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2916 defer cancel()
2917 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
2918}
2919
2920func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
2921 cClient, err := dh.coreClient.GetCoreServiceClient()
2922 if err != nil || cClient == nil {
2923 return err
2924 }
2925 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2926 defer cancel()
2927 _, err = cClient.DeviceUpdate(subCtx, device)
2928 return err
2929}
2930
khenaidoodc2116e2021-10-19 17:33:19 -04002931func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002932 cClient, err := dh.coreClient.GetCoreServiceClient()
2933 if err != nil || cClient == nil {
2934 return nil, err
2935 }
2936 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2937 defer cancel()
2938 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
2939}
2940
khenaidoodc2116e2021-10-19 17:33:19 -04002941func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002942 cClient, err := dh.coreClient.GetCoreServiceClient()
2943 if err != nil || cClient == nil {
2944 return err
2945 }
2946 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2947 defer cancel()
2948 _, err = cClient.SendPacketIn(subCtx, pkt)
2949 return err
2950}
2951
2952func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
2953 cClient, err := dh.coreClient.GetCoreServiceClient()
2954 if err != nil || cClient == nil {
2955 return err
2956 }
2957 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2958 defer cancel()
2959 _, err = cClient.PortCreated(subCtx, port)
2960 return err
2961}
2962
khenaidoodc2116e2021-10-19 17:33:19 -04002963func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002964 cClient, err := dh.coreClient.GetCoreServiceClient()
2965 if err != nil || cClient == nil {
2966 return err
2967 }
2968 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2969 defer cancel()
2970 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
2971 return err
2972}
2973
khenaidoodc2116e2021-10-19 17:33:19 -04002974func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002975 cClient, err := dh.coreClient.GetCoreServiceClient()
2976 if err != nil || cClient == nil {
2977 return err
2978 }
2979 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2980 defer cancel()
2981 _, err = cClient.PortStateUpdate(subCtx, portState)
2982 return err
2983}
2984
khenaidoodc2116e2021-10-19 17:33:19 -04002985func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002986 cClient, err := dh.coreClient.GetCoreServiceClient()
2987 if err != nil || cClient == nil {
2988 return nil, err
2989 }
2990 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2991 defer cancel()
2992 return cClient.GetDevicePort(subCtx, portFilter)
2993}
2994
2995/*
2996Helper functions to communicate with child adapter
2997*/
2998
khenaidoodc2116e2021-10-19 17:33:19 -04002999func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003000 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3001 if err != nil || aClient == nil {
3002 return err
3003 }
3004 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3005 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3006 defer cancel()
3007 _, err = aClient.OmciIndication(subCtx, response)
3008 return err
3009}
3010
khenaidoodc2116e2021-10-19 17:33:19 -04003011func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003012 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3013 if err != nil || aClient == nil {
3014 return err
3015 }
3016 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3017 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3018 defer cancel()
3019 _, err = aClient.OnuIndication(subCtx, onuInd)
3020 return err
3021}
3022
khenaidoodc2116e2021-10-19 17:33:19 -04003023func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003024 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3025 if err != nil || aClient == nil {
3026 return err
3027 }
3028 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3029 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3030 defer cancel()
3031 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3032 return err
3033}
3034
khenaidoodc2116e2021-10-19 17:33:19 -04003035func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003036 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3037 if err != nil || aClient == nil {
3038 return err
3039 }
3040 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3041 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3042 defer cancel()
3043 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3044 return err
3045}
3046
khenaidoodc2116e2021-10-19 17:33:19 -04003047func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003048 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3049 if err != nil || aClient == nil {
3050 return err
3051 }
3052 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3053 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3054 defer cancel()
3055 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3056 return err
3057}
3058
3059/*
3060Helper functions for remote communication
3061*/
3062
3063// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3064// supports is deleted
3065func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3066 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3067
3068 dh.lockChildAdapterClients.Lock()
3069 defer dh.lockChildAdapterClients.Unlock()
3070 if _, ok := dh.childAdapterClients[endpoint]; ok {
3071 // Already set
3072 return nil
3073 }
3074
3075 // Setup child's adapter grpc connection
3076 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003077 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3078 dh.cfg.AdapterEndpoint,
3079 endpoint,
3080 dh.onuAdapterRestarted); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003081 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3082 return err
3083 }
khenaidoo27e7ac92021-12-08 14:43:09 -05003084 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.setAndTestOnuInterAdapterServiceHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003085
3086 // Wait until we have a connection to the child adapter.
3087 // Unlimited retries or until context expires
3088 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3089 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3090 for {
3091 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3092 if err == nil && client != nil {
3093 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3094 break
3095 }
3096 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3097 // Backoff
3098 if err = backoff.Backoff(subCtx); err != nil {
3099 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3100 break
3101 }
3102 }
3103 return nil
3104}
3105
khenaidoodc2116e2021-10-19 17:33:19 -04003106func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003107
3108 // First check from cache
3109 dh.lockChildAdapterClients.RLock()
3110 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3111 dh.lockChildAdapterClients.RUnlock()
3112 return cgClient.GetOnuInterAdapterServiceClient()
3113 }
3114 dh.lockChildAdapterClients.RUnlock()
3115
3116 // Set the child connection - can occur on restarts
3117 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3118 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3119 cancel()
3120 if err != nil {
3121 return nil, err
3122 }
3123
3124 // Get the child client now
3125 dh.lockChildAdapterClients.RLock()
3126 defer dh.lockChildAdapterClients.RUnlock()
3127 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3128 return cgClient.GetOnuInterAdapterServiceClient()
3129 }
3130 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3131}
3132
3133func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3134 dh.lockChildAdapterClients.Lock()
3135 defer dh.lockChildAdapterClients.Unlock()
3136 for key, client := range dh.childAdapterClients {
3137 client.Stop(ctx)
3138 delete(dh.childAdapterClients, key)
3139 }
3140}
3141
3142// TODO: Any action the adapter needs to do following a onu adapter restart?
3143func (dh *DeviceHandler) onuAdapterRestarted(ctx context.Context, endPoint string) error {
khenaidoo7eb2d672021-10-22 19:08:50 -04003144 logger.Warnw(ctx, "onu-adapter-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003145 return nil
3146}
3147
khenaidoo27e7ac92021-12-08 14:43:09 -05003148// setAndTestOnuInterAdapterServiceHandler is used to test whether the remote gRPC service is up
3149func (dh *DeviceHandler) setAndTestOnuInterAdapterServiceHandler(ctx context.Context, conn *grpc.ClientConn, clientConn *common.Connection) interface{} {
3150 // The onu adapter needs to know whether the olt adapter can connect to it. Since the olt adapter
3151 // has a grpc client connection per device handler (i.e. per olt device) to the onu adapter
3152 // then the onu adapter needs to know whether that specific client can connect to it. Because the
3153 // client uses a polling mechanism then not all grpc clients could be connected at the same time,
3154 // a maximum difference of 5 sec. We therefore add the parent device as additional contextual information
3155 // to this request.
3156 dh.lockDevice.RLock()
3157 if dh.device != nil {
3158 clientConn.ContextInfo = dh.device.Id
3159 }
3160 dh.lockDevice.RUnlock()
khenaidoodc2116e2021-10-19 17:33:19 -04003161 svc := onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo27e7ac92021-12-08 14:43:09 -05003162 if h, err := svc.GetHealthStatus(ctx, clientConn); err != nil || h.State != health.HealthStatus_HEALTHY {
khenaidoo106c61a2021-08-11 18:05:46 -04003163 return nil
3164 }
3165 return svc
3166}
Girish Gowdra950326e2021-11-05 12:43:24 -07003167
3168func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3169 dh.lockDevice.Lock()
3170 defer dh.lockDevice.Unlock()
3171 dh.isDeviceDeletionInProgress = flag
3172}
3173
3174func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3175 dh.lockDevice.RLock()
3176 defer dh.lockDevice.RUnlock()
3177 return dh.isDeviceDeletionInProgress
3178}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003179
3180// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3181// Returns false if waiting timed out.
3182func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3183 c := make(chan struct{})
3184 go func() {
3185 defer close(c)
3186 wg.Wait()
3187 }()
3188 select {
3189 case <-c:
3190 return true // completed normally
3191 case <-time.After(timeout):
3192 return false // timed out
3193 }
3194}