blob: 2bdbbb1ae8475b6b336a9d0cd4717b9373394289 [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
kesavandb9f54fd2021-11-25 20:08:04 +05301151// ProxyOmciRequests sends the proxied OMCI message to the target device
1152func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
1153 if omciMsgs.GetProxyAddress() == nil {
1154 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1155 if err != nil {
1156 return olterrors.NewErrNotFound("onu", log.Fields{
1157 "parent-device-id": dh.device.Id,
1158 "child-device-id": omciMsgs.ChildDeviceId}, err)
1159 }
1160 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1161 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1162 return olterrors.NewErrCommunication("send-failed", log.Fields{
1163 "parent-device-id": dh.device.Id,
1164 "child-device-id": omciMsgs.ChildDeviceId}, err)
1165 }
1166 } else {
1167 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1168 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1169 return olterrors.NewErrCommunication("send-failed", log.Fields{
1170 "parent-device-id": dh.device.Id,
1171 "child-device-id": omciMsgs.ChildDeviceId}, err)
1172 }
1173 }
1174 return nil
1175}
1176
1177func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1178 var intfID uint32
1179 var onuID uint32
1180 var connectStatus common.ConnectStatus_Types
1181 if onuDevice != nil {
1182 intfID = onuDevice.ProxyAddress.GetChannelId()
1183 onuID = onuDevice.ProxyAddress.GetOnuId()
1184 connectStatus = onuDevice.ConnectStatus
1185 } else {
1186 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1187 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1188 connectStatus = omciMsgs.GetConnectStatus()
1189 }
1190 if connectStatus != voltha.ConnectStatus_REACHABLE {
1191 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1192
1193 return olterrors.NewErrCommunication("unreachable", log.Fields{
1194 "intf-id": intfID,
1195 "onu-id": onuID}, nil)
1196 }
1197
1198 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1199 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1200
1201 onuSecOmciMsgList := omciMsgs.GetMessages()
1202
1203 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1204
1205 var omciMessage *oop.OmciMsg
1206 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1207 hex.Encode(hexPkt, onuSecOmciMsg)
1208 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1209
1210 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1211 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1212 //https://jira.opencord.org/browse/VOL-4604
1213 transid := extractOmciTransactionID(onuSecOmciMsg)
1214 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1215 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1216
1217 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1218 if err != nil {
1219 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1220 "intf-id": intfID,
1221 "onu-id": onuID,
1222 "message": omciMessage}, err)
1223 }
1224 }
1225 return nil
1226}
1227
khenaidoo106c61a2021-08-11 18:05:46 -04001228// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001229func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001230 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 -07001231
1232 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001233 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001234 if err != nil {
1235 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001236 "parent-device-id": dh.device.Id,
1237 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001238 }
khenaidoo106c61a2021-08-11 18:05:46 -04001239 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1240 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001241 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001242 "parent-device-id": dh.device.Id,
1243 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001244 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001245 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001246 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1247 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001248 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001249 "parent-device-id": dh.device.Id,
1250 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001251 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001252 }
1253 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301254}
1255
khenaidoodc2116e2021-10-19 17:33:19 -04001256func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001257 var intfID uint32
1258 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001259 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001260 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001261 intfID = onuDevice.ProxyAddress.GetChannelId()
1262 onuID = onuDevice.ProxyAddress.GetOnuId()
1263 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001264 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001265 intfID = omciMsg.GetProxyAddress().GetChannelId()
1266 onuID = omciMsg.GetProxyAddress().GetOnuId()
1267 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001268 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001269 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001270 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 -08001271
Thomas Lee S94109f12020-03-03 16:39:29 +05301272 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001273 "intf-id": intfID,
1274 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001275 }
1276
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001277 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1278 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301279 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001280 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001281 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1282 hex.Encode(hexPkt, omciMsg.Message)
1283 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1284
1285 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1286 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1287 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001288 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001289 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001290
Neha Sharma8f4e4322020-08-06 10:51:53 +00001291 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001292 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301293 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001294 "intf-id": intfID,
1295 "onu-id": onuID,
1296 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001297 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001299}
1300
David K. Bainbridge794735f2020-02-11 21:01:37 -08001301func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301302 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 -07001303 if err := dh.flowMgr[intfID].AddOnuInfoToFlowMgrCacheAndKvStore(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001304 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001305 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001306 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301307 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301308 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001309 st, _ := status.FromError(err)
1310 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001311 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1312
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001313 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301314 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001315 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001316 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001317 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001318 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001319 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001320}
1321
Mahir Gunyelb0046752021-02-26 13:51:05 -08001322func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001323 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001324 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001325
Mahir Gunyelb0046752021-02-26 13:51:05 -08001326 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001327 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301328
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301329 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001330 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001331 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301332
1333 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1334 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1335 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1336 OnuLosRaise event sent for it */
1337 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1338 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1339 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001340 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301341 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1342 "currentIntfId": onuDiscInd.GetIntfId()})
1343 // TODO:: Should we need to ignore raising OnuLosClear event
1344 // when onu connected to different PON?
1345 }
1346 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1347 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1348 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001349 go func() {
1350 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001351 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001352 }
1353 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301354 }
1355 return true
1356 })
1357
Neha Sharma96b7bf22020-06-15 10:37:32 +00001358 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001359 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001360 }
1361
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001362 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001363
1364 // check the ONU is already know to the OLT
1365 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001366 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001367 ParentId: dh.device.Id,
1368 SerialNumber: sn,
1369 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001370
1371 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001372 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 -08001373 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001374 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 -08001375 switch e.Code() {
1376 case codes.Internal:
1377 // this probably means NOT FOUND, so just create a new device
1378 onuDevice = nil
1379 case codes.DeadlineExceeded:
1380 // if the call times out, cleanup and exit
1381 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001382 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001383 }
1384 }
1385 }
1386
1387 if onuDevice == nil {
1388 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001389 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001390 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001391 ponintfid := onuDiscInd.GetIntfId()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001392 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001393
Neha Sharma96b7bf22020-06-15 10:37:32 +00001394 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001395
1396 if err != nil {
1397 // if we can't create an ID in resource manager,
1398 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001399 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001400 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001401 "pon-intf-id": ponintfid,
1402 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001403 }
1404
khenaidoodc2116e2021-10-19 17:33:19 -04001405 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001406 ParentId: dh.device.Id,
1407 ParentPortNo: parentPortNo,
1408 ChannelId: channelID,
1409 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1410 SerialNumber: sn,
1411 OnuId: onuID,
1412 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001413 dh.discOnus.Delete(sn)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001414 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 +05301415 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001416 "pon-intf-id": ponintfid,
1417 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001418 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001419 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 -07001420 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001421 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001422 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301423 log.Fields{"onuDevice": onuDevice,
1424 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001425 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301426 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001427 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001428
khenaidoo106c61a2021-08-11 18:05:46 -04001429 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1430 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1431 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1432 cancel()
1433 if err != nil {
1434 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1435 }
1436
Matteo Scandolo945e4012019-12-12 14:16:11 -08001437 // we can now use the existing ONU Id
1438 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001439 //Insert the ONU into cache to use in OnuIndication.
1440 //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 +00001441 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001442 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301443 "intfId": onuDiscInd.GetIntfId(),
1444 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001445 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001446
khenaidoo106c61a2021-08-11 18:05:46 -04001447 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301448 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001449 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301450 log.Fields{"onu": onuDev,
1451 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001452
khenaidoodc2116e2021-10-19 17:33:19 -04001453 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001454 DeviceId: onuDevice.Id,
1455 ParentDeviceId: dh.device.Id,
1456 OperStatus: common.OperStatus_DISCOVERED,
1457 ConnStatus: common.ConnectStatus_REACHABLE,
1458 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301459 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001460 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001461 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001462 }
khenaidoo106c61a2021-08-11 18:05:46 -04001463
Neha Sharma96b7bf22020-06-15 10:37:32 +00001464 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001465 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301466 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001467 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001468 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001469 }
1470 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001471}
1472
Mahir Gunyelb0046752021-02-26 13:51:05 -08001473func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001474
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001475 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001476 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001477 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001478 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001479 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301480 log.Fields{"onuId": onuInd.OnuId,
1481 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301482 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001483 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001484 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301485
David K. Bainbridge794735f2020-02-11 21:01:37 -08001486 errFields := log.Fields{"device-id": dh.device.Id}
1487
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301488 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1489
Mahir Gunyele77977b2019-06-27 05:36:22 -07001490 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1491 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001492 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001493 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001494 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001495 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1496 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001497 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001498 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001499 errFields["onu-id"] = onuInd.OnuId
1500 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001501 }
khenaidoodc2116e2021-10-19 17:33:19 -04001502 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001503 ParentId: dh.device.Id,
1504 SerialNumber: serialNumber,
1505 OnuId: onuInd.OnuId,
1506 ParentPortNo: ponPort,
1507 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001508 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001509
David K. Bainbridge794735f2020-02-11 21:01:37 -08001510 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001511 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001512 }
1513
David K. Bainbridge794735f2020-02-11 21:01:37 -08001514 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001515 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001516 "previousIntfId": onuDevice.ParentPortNo,
1517 "currentIntfId": ponPort})
1518 }
1519
1520 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001521 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301522 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1523 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301524 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001525 }
1526 if !foundInCache {
1527 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1528
khenaidoo106c61a2021-08-11 18:05:46 -04001529 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 -08001530
1531 }
kesavand7cf3a052020-08-28 12:49:18 +05301532 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001533 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001534 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301535 }
1536 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001537 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001538 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001539 }
1540 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001541}
1542
Neha Sharma96b7bf22020-06-15 10:37:32 +00001543func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001544 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 -07001545 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1546 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1547 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1548 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001549 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001550 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1551 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001552 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001553 onuInd.OperState = "down"
1554 }
1555 }
1556
David K. Bainbridge794735f2020-02-11 21:01:37 -08001557 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001558 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001559 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 -04001560
khenaidoodc2116e2021-10-19 17:33:19 -04001561 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001562 DeviceId: onuDevice.Id,
1563 OnuIndication: onuInd,
1564 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001565 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301566 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001567 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001568 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001569 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001570 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001571 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001572 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001573 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001574 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001575 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001576}
1577
cuilin20187b2a8c32019-03-26 19:52:28 -07001578func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1579 if serialNum != nil {
1580 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001581 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001582 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001583}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001584func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1585 decodedStr, err := hex.DecodeString(serialNum[4:])
1586 if err != nil {
1587 return nil, err
1588 }
1589 return &oop.SerialNumber{
1590 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001591 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001592 }, nil
1593}
cuilin20187b2a8c32019-03-26 19:52:28 -07001594
1595func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001596 if len(vendorSpecific) > 3 {
1597 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1598 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1599 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1600 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1601 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1602 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1603 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1604 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1605 return tmp
1606 }
1607 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001608}
1609
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001610//UpdateFlowsBulk upates the bulk flow
1611func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301612 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001613}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001614
1615//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001616func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1617 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301618 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001619 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301620 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001621
khenaidoodc2116e2021-10-19 17:33:19 -04001622 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001623 ParentId: dh.device.Id,
1624 OnuId: onuID,
1625 ParentPortNo: parentPort,
1626 })
1627
Girish Gowdru0c588b22019-04-23 23:24:56 -04001628 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001629 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001630 "intf-id": parentPort,
1631 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001632 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001633 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 -08001634 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301635}
1636
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001637// SendPacketInToCore sends packet-in to core
1638// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1639// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001640func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001641 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001642 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001643 "port": logicalPort,
1644 "packet": hex.EncodeToString(packetPayload),
1645 "device-id": dh.device.Id,
1646 })
1647 }
khenaidoo106c61a2021-08-11 18:05:46 -04001648
khenaidoodc2116e2021-10-19 17:33:19 -04001649 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001650 DeviceId: dh.device.Id,
1651 Port: logicalPort,
1652 Packet: packetPayload,
1653 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301654 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001655 "source": "adapter",
1656 "destination": "core",
1657 "device-id": dh.device.Id,
1658 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001659 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001660 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001661 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001662 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001663 "packet": hex.EncodeToString(packetPayload),
1664 "device-id": dh.device.Id,
1665 })
1666 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001667 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001668}
1669
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001670// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001672 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001673
1674 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1675 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001676 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001677 }
1678
Kent Hagermane6ff1012020-07-14 15:07:53 -04001679 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001680 metrics := dh.metrics.GetSubscriberMetrics()
1681 for _, m := range pmConfigs.Metrics {
1682 metrics[m.Name].Enabled = m.Enabled
1683
1684 }
1685 }
1686}
1687
khenaidoodc2116e2021-10-19 17:33:19 -04001688func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001689 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001690 var errorsList []error
1691
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001692 if dh.getDeviceDeletionInProgressFlag() {
1693 // The device itself is going to be reset as part of deletion. So nothing to be done.
1694 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1695 return nil
1696 }
1697
Girish Gowdru0c588b22019-04-23 23:24:56 -04001698 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001699 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001700 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001701
Neha Sharma96b7bf22020-06-15 10:37:32 +00001702 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301703 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001704 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301705 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001706 if flow_utils.HasGroup(flow) {
1707 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1708 } else {
1709 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1710 }
Girish Gowdracefae192020-03-19 18:14:10 -07001711 if err != nil {
1712 errorsList = append(errorsList, err)
1713 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001714 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301715
1716 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001717 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001718 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301719 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001720 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301721 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001722 if flow_utils.HasGroup(flow) {
1723 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1724 } else {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001725 if dh.flowMgr == nil || dh.flowMgr[ponIf] == nil {
1726 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1727 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1728 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1729 } else {
1730 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1731 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001732 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001733 if err != nil {
1734 errorsList = append(errorsList, err)
1735 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301736 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001737 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001738
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001739 return errorsList
1740}
1741
1742func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1743 var err error
1744 var errorsList []error
1745
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001746 if dh.getDeviceDeletionInProgressFlag() {
1747 // The device itself is going to be reset as part of deletion. So nothing to be done.
1748 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1749 return nil
1750 }
1751
Girish Gowdracefae192020-03-19 18:14:10 -07001752 // 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 +00001753 if groups != nil {
1754 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001755 // err = dh.groupMgr.AddGroup(ctx, group)
1756 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001757 if err != nil {
1758 errorsList = append(errorsList, err)
1759 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001760 }
1761 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001762 // err = dh.groupMgr.ModifyGroup(ctx, group)
1763 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001764 if err != nil {
1765 errorsList = append(errorsList, err)
1766 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001767 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001768 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001769 // err = dh.groupMgr.DeleteGroup(ctx, group)
1770 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001771 if err != nil {
1772 errorsList = append(errorsList, err)
1773 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001774 }
1775 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001776
1777 return errorsList
1778}
1779
1780//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001781func (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 -07001782
1783 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001784
1785 if dh.getDeviceDeletionInProgressFlag() {
1786 // The device itself is going to be reset as part of deletion. So nothing to be done.
1787 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1788 return nil
1789 }
1790
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001791 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1792 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1793 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001794 if len(errorsList) > 0 {
1795 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1796 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001797 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001798 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301799}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001801//DisableDevice disables the given device
1802//It marks the following for the given device:
1803//Device-Handler Admin-State : down
1804//Device Port-State: UNKNOWN
1805//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001806func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001807 /* On device disable ,admin state update has to be done prior sending request to agent since
1808 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001809 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001810 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001811 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001812 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001813 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001814 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001815 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001816 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001817 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001818 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301819
1820 dh.discOnus = sync.Map{}
1821 dh.onus = sync.Map{}
1822
Thomas Lee S85f37312020-04-03 17:06:12 +05301823 //stopping the stats collector
1824 dh.stopCollector <- true
1825
Neha Sharma96b7bf22020-06-15 10:37:32 +00001826 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001827 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301828 //Update device Admin state
1829 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001830
kdarapu1afeceb2020-02-12 01:38:09 -05001831 // 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 -04001832 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001833 DeviceId: cloned.Id,
1834 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
1835 OperStatus: voltha.OperStatus_UNKNOWN,
1836 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001837 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001838 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001839 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001840 return nil
1841}
1842
Neha Sharma96b7bf22020-06-15 10:37:32 +00001843func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001844 // Update onu state as unreachable in onu adapter
1845 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301846 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04001847
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001848 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001849 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001850 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001851 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 -04001852 }
1853 if onuDevices != nil {
1854 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04001855 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001856 DeviceId: onuDevice.Id,
1857 OnuIndication: &onuInd,
1858 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001859 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001860 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001861 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001862 }
1863
1864 }
1865 }
1866
1867}
1868
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001869//ReenableDevice re-enables the olt device after disable
1870//It marks the following for the given device:
1871//Device-Handler Admin-State : up
1872//Device Port-State: ACTIVE
1873//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001874func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001875 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301876 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001877 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301878 }
1879 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001880 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001881
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001882 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04001883 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001884 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001885 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001886 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
1887 } else {
1888 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1889 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
1890 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001891 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001892 if retError == nil {
1893 //Update the device oper status as ACTIVE
1894 device.OperStatus = voltha.OperStatus_ACTIVE
1895 } else {
1896 //Update the device oper status as FAILED
1897 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001898 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001899 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001900
khenaidoodc2116e2021-10-19 17:33:19 -04001901 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001902 DeviceId: device.Id,
1903 OperStatus: device.OperStatus,
1904 ConnStatus: device.ConnectStatus,
1905 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301906 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001907 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001908 "connect-status": device.ConnectStatus,
1909 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001910 }
kesavand39e0aa32020-01-28 20:58:50 -05001911
Neha Sharma96b7bf22020-06-15 10:37:32 +00001912 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001913
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001914 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001915}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001916
npujarec5762e2020-01-01 14:08:48 +05301917func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001918 var uniID uint32
1919 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301920 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001921 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001922 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001923 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001924 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001925 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001926 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001927 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001928 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001929 for _, tpID := range tpIDList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001930 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001931 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001932 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001933 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001934 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001935 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001936 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001937 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301938 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001939 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1940 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001941 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301942 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001943 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001944 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001945 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 +00001946 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001947 }
1948 return nil
1949}
1950
Devmalya Paul495b94a2019-08-27 19:42:00 -04001951// 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 +05301952func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001953 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001954 /* Clear the KV store data associated with the all the UNI ports
1955 This clears up flow data and also resource map data for various
1956 other pon resources like alloc_id and gemport_id
1957 */
Girish Gowdra950326e2021-11-05 12:43:24 -07001958
1959 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001960 var wg sync.WaitGroup
1961 wg.Add(1) // for the mcast routine below to finish
1962 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
1963 for _, flMgr := range dh.flowMgr {
1964 wg.Add(1) // for the flow handler routine below to finish
1965 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
1966 }
1967 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
1968 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
1969 } else {
1970 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
1971 }
Girish Gowdra950326e2021-11-05 12:43:24 -07001972
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001973 dh.cleanupDeviceResources(ctx)
1974 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 -04001975 // Stop the Stats collector
1976 dh.stopCollector <- true
1977 // stop the heartbeat check routine
1978 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301979 dh.lockDevice.RLock()
1980 // Stop the read indication only if it the routine is active
1981 if dh.isReadIndicationRoutineActive {
1982 dh.stopIndications <- true
1983 }
1984 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001985 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001986 //Reset the state
1987 if dh.Client != nil {
1988 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301989 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001990 }
1991 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07001992 // There is no need to update the core about operation status and connection status of the OLT.
1993 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1994 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1995 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001996
khenaidoo7eb2d672021-10-22 19:08:50 -04001997 // Stop the adapter grpc clients for that parent device
1998 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001999 return nil
2000}
Kent Hagermane6ff1012020-07-14 15:07:53 -04002001func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002002
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002003 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302004 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002005 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002006 var err error
Girish Gowdrabcf98af2021-07-01 08:24:42 -07002007 onuGemData := dh.flowMgr[ponPort].getOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002008 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002009 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002010 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002011 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302012 }
2013 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002014 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx, ponPort)
2015 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx, ponPort)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002016 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2017 logger.Debug(ctx, err)
2018 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002019 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002020 }
A R Karthick1f85b802019-10-11 05:06:05 +00002021
Devmalya Paul495b94a2019-08-27 19:42:00 -04002022 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302023 dh.onus.Range(func(key interface{}, value interface{}) bool {
2024 dh.onus.Delete(key)
2025 return true
2026 })
2027
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002028 /*Delete discovered ONU map for the device*/
2029 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2030 dh.discOnus.Delete(key)
2031 return true
2032 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002033}
2034
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002035//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002036func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002037 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302038 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002039 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002040 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002041 return nil
2042}
2043
David K. Bainbridge794735f2020-02-11 21:01:37 -08002044func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002045 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002046 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002047 "packet-indication": *packetIn,
2048 "device-id": dh.device.Id,
2049 "packet": hex.EncodeToString(packetIn.Pkt),
2050 })
2051 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002052 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002053 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002054 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002055 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002056 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002057 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002058 "logical-port-num": logicalPortNum,
2059 "device-id": dh.device.Id,
2060 "packet": hex.EncodeToString(packetIn.Pkt),
2061 })
2062 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002063
khenaidoodc2116e2021-10-19 17:33:19 -04002064 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002065 DeviceId: dh.device.Id,
2066 Port: logicalPortNum,
2067 Packet: packetIn.Pkt,
2068 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302069 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002070 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302071 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002072 "device-id": dh.device.Id,
2073 "packet": hex.EncodeToString(packetIn.Pkt),
2074 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002076
Matteo Scandolo92186242020-06-12 10:54:18 -07002077 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002078 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002079 "packet": hex.EncodeToString(packetIn.Pkt),
2080 "device-id": dh.device.Id,
2081 })
2082 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002083 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002084}
2085
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002086// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002087func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002088 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002089 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002090 "device-id": dh.device.Id,
2091 "egress-port-no": egressPortNo,
2092 "pkt-length": len(packet.Data),
2093 "packet": hex.EncodeToString(packet.Data),
2094 })
2095 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002096
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002097 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002098 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002099 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2100 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302101 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2102 // Do not packet-out lldp packets on uni port.
2103 // ONOS has no clue about uni/nni ports, it just packets out on all
2104 // available ports on the Logical Switch. It should not be interested
2105 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002106 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002107 "device-id": dh.device.Id,
2108 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302109 return nil
2110 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002111 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2112 if innerEthType == 0x8100 {
2113 // q-in-q 802.1ad or 802.1q double tagged packet.
2114 // slice out the outer tag.
2115 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002116 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002117 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002118 "packet-data": hex.EncodeToString(packet.Data),
2119 "device-id": dh.device.Id,
2120 })
2121 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002122 }
2123 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002124 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2125 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2126 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002127
Girish Gowdra9602eb42020-09-09 15:50:39 -07002128 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002129 if err != nil {
2130 // In this case the openolt agent will receive the gemPortID as 0.
2131 // The agent tries to retrieve the gemPortID in this case.
2132 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002133 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002134 "intf-id": intfID,
2135 "onu-id": onuID,
2136 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002137 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302138 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002139 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002140 }
2141
2142 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002143 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002144 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002145 "egress-port-no": egressPortNo,
2146 "intf-id": intfID,
2147 "onu-id": onuID,
2148 "uni-id": uniID,
2149 "gem-port-id": gemPortID,
2150 "packet": hex.EncodeToString(packet.Data),
2151 "device-id": dh.device.Id,
2152 })
2153 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002154
npujarec5762e2020-01-01 14:08:48 +05302155 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302156 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002157 "source": "adapter",
2158 "destination": "onu",
2159 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002160 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002161 "oni-id": onuID,
2162 "uni-id": uniID,
2163 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002164 "packet": hex.EncodeToString(packet.Data),
2165 "device-id": dh.device.Id,
2166 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002167 }
2168 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002169 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002170 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002171 return olterrors.NewErrInvalidValue(log.Fields{
2172 "egress-nni-port": egressPortNo,
2173 "device-id": dh.device.Id,
2174 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002175 }
2176 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002177
Matteo Scandolo92186242020-06-12 10:54:18 -07002178 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002179 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002180 "uplink-pkt": uplinkPkt,
2181 "packet": hex.EncodeToString(packet.Data),
2182 "device-id": dh.device.Id,
2183 })
2184 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002185
npujarec5762e2020-01-01 14:08:48 +05302186 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002187 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2188 "packet": hex.EncodeToString(packet.Data),
2189 "device-id": dh.device.Id,
2190 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002191 }
2192 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002193 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302194 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002195 "egressPortType": egressPortType,
2196 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302197 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002198 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002199 }
2200 return nil
2201}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002202
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002203func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2204 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002205}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302206
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002207func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002208
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302209 // start the heartbeat check towards the OLT.
2210 var timerCheck *time.Timer
2211
2212 for {
2213 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2214 select {
2215 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002216 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002217 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002218 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302219 if timerCheck == nil {
2220 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002221 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302222 }
2223 } else {
2224 if timerCheck != nil {
2225 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002226 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302227 }
2228 timerCheck = nil
2229 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002230 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302231 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302232 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302233 }
2234 cancel()
2235 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002236 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302237 return
2238 }
2239 }
2240}
2241
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002242func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002243 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002244 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002245 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2246 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2247 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2248 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2249 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002250 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002251 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2252 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002253 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302254
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002255 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2256 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002257 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002258 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002259 DeviceId: dh.device.Id,
2260 OperStatus: voltha.OperStatus_UNKNOWN,
2261 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2262 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002263 _ = 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 -04002264 }
khenaidoo106c61a2021-08-11 18:05:46 -04002265
khenaidoodc2116e2021-10-19 17:33:19 -04002266 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002267 DeviceId: dh.device.Id,
2268 PortTypeFilter: 0,
2269 OperStatus: voltha.OperStatus_UNKNOWN,
2270 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002271 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002272 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002273
2274 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002275 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002276 cloned := proto.Clone(device).(*voltha.Device)
2277 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2278 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2279 dh.device = cloned // update local copy of the device
2280 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002281
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002282 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002283 // Stop the Stats collector
2284 dh.stopCollector <- true
2285 // stop the heartbeat check routine
2286 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002287
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002288 dh.lockDevice.RLock()
2289 // Stop the read indication only if it the routine is active
2290 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2291 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2292 // on next execution of the readIndication routine.
2293 if dh.isReadIndicationRoutineActive {
2294 dh.stopIndications <- true
2295 }
2296 dh.lockDevice.RUnlock()
2297
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002298 var wg sync.WaitGroup
2299 wg.Add(1) // for the multicast handler routine
2300 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002301 for _, flMgr := range dh.flowMgr {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002302 wg.Add(1) // for the flow handler routine
2303 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2304 }
2305 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2306 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2307 } else {
2308 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002309 }
2310
Gamze Abakac2c32a62021-03-11 11:44:18 +00002311 //reset adapter reconcile flag
2312 dh.adapterPreviouslyConnected = false
2313
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002314 dh.transitionMap.Handle(ctx, DeviceInit)
2315
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302316 }
2317}
kesavand39e0aa32020-01-28 20:58:50 -05002318
2319// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002320func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2321 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2322 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002323}
2324
2325// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002326func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2327 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2328 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002329}
2330
kdarapu1afeceb2020-02-12 01:38:09 -05002331//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 +00002332func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2333 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002334 if port.GetType() == voltha.Port_ETHERNET_NNI {
2335 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002336 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302337 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302338 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002339 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002340 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002341 }
2342 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002343 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002344 ponIntf := &oop.Interface{IntfId: ponID}
2345 var operStatus voltha.OperStatus_Types
2346 if enablePort {
2347 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302348 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002349
2350 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302351 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002352 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002353 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002354 }
2355 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002356 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002357 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002358 } else {
2359 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302360 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002361 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302362 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002363 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002364 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002365 }
2366 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002367 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002368 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002369 }
khenaidoodc2116e2021-10-19 17:33:19 -04002370 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002371 DeviceId: dh.device.Id,
2372 PortType: voltha.Port_PON_OLT,
2373 PortNo: port.PortNo,
2374 OperStatus: operStatus,
2375 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302376 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302377 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002378 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002379 }
2380 return nil
2381}
2382
kdarapu1afeceb2020-02-12 01:38:09 -05002383//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002384func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002385 // Disable the port and update the oper_port_status to core
2386 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002387 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002388 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302390 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302391 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002392 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002393 }
2394 }
2395 }
2396 return nil
2397}
2398
2399//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002400func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2401 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2402 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002403 if port.Type == voltha.Port_ETHERNET_NNI {
2404 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002405 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002406 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002407 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002408 }
2409 }
2410 if port.Type == voltha.Port_PON_OLT {
2411 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002412 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002413 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002414 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002415 }
2416 }
2417 }
2418}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002419
2420// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002421func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002422 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002423 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002424 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002425
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002426 var sn *oop.SerialNumber
2427 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002428 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302429 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002430 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302431 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002432 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002433 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002434
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002435 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002436 //clear PON resources associated with ONU
2437 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, intfID, onuID)
2438 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2439 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2440 "device-id": dh.device.Id,
2441 "intf-id": intfID,
2442 "onuID": onuID,
2443 "err": err})
2444 } else {
2445 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
2446 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2447 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2448 "device-id": dh.device.Id,
2449 "onu-device": onu,
2450 "err": err})
2451 }
2452 // Clear flowids for gem cache.
2453 for _, gem := range onuGem.GemPorts {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002454 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, intfID, gem)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002455 }
Girish Gowdra197acc12021-08-16 10:59:45 -07002456 if err := dh.flowMgr[intfID].RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx, intfID, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002457 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2458 "intf-id": intfID,
2459 "onu-device": onu,
2460 "onu-gem": onuGem,
2461 "err": err})
2462 //Not returning error on cleanup.
2463 }
2464 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302465
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002466 }
Himani Chawlabcc95852021-10-27 10:55:40 +05302467 dh.resourceMgr[intfID].FreeonuID(ctx, intfID, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002468 dh.onus.Delete(onuKey)
2469 dh.discOnus.Delete(onuSn)
2470
2471 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002472 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302473 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302474 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002475 "onu-id": onuID}, err).Log()
2476 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002477
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002478 return nil
2479}
Girish Gowdracefae192020-03-19 18:14:10 -07002480
2481func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002482 for _, field := range flow_utils.GetOfbFields(flow) {
2483 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002484 return field.GetPort()
2485 }
2486 }
2487 return InvalidPort
2488}
2489
2490func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002491 for _, action := range flow_utils.GetActions(flow) {
2492 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002493 if out := action.GetOutput(); out != nil {
2494 return out.GetPort()
2495 }
2496 }
2497 }
2498 return InvalidPort
2499}
2500
Girish Gowdracefae192020-03-19 18:14:10 -07002501func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2502 inPort := getInPortFromFlow(flow)
2503 outPort := getOutPortFromFlow(flow)
2504
2505 if inPort == InvalidPort || outPort == InvalidPort {
2506 return inPort, outPort
2507 }
2508
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002509 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002510 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002511 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002512 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002513 return uniPort, outPort
2514 }
2515 }
2516 } else {
2517 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002518 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002519 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002520 return inPort, uniPort
2521 }
2522 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002523 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002524 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002525 return uniPort, outPort
2526 }
2527 }
2528 }
2529
2530 return InvalidPort, InvalidPort
2531}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002532
2533func extractOmciTransactionID(omciPkt []byte) uint16 {
2534 if len(omciPkt) > 3 {
2535 d := omciPkt[0:2]
2536 transid := binary.BigEndian.Uint16(d)
2537 return transid
2538 }
2539 return 0
2540}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002541
2542// StoreOnuDevice stores the onu parameters to the local cache.
2543func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2544 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2545 dh.onus.Store(onuKey, onuDevice)
2546}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002547
khenaidoodc2116e2021-10-19 17:33:19 -04002548func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002549 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002550 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002551 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002552 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002553 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002554 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002555 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002556 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2557 return nil, err
2558 }
2559 ID = device.ProxyAddress.GetOnuId()
2560 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2561 valueparam.Onu = &Onu
2562 valueparam.Value = value
2563
2564 // This API is unsupported until agent patch is added
2565 resp.Unsupported = uint32(value)
2566 _ = ctx
2567
2568 // Uncomment this code once agent changes are complete and tests
2569 /*
2570 resp, err = dh.Client.GetValue(ctx, valueparam)
2571 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002572 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002573 return nil, err
2574 }
2575 */
2576
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002577 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 -08002578 return resp, nil
2579}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002580
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002581func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002582 // Default to PON0
2583 var intfID uint32
2584 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002585 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002586 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002587 }
2588 return intfID
2589}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002590
Mahir Gunyelb0046752021-02-26 13:51:05 -08002591func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2592 dh.perPonOnuIndicationChannelLock.Lock()
2593 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2594 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002595 return ch.indicationChannel
2596 }
2597 channels := onuIndicationChannels{
2598 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002599 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002600 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002601 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002602 stopChannel: make(chan struct{}),
2603 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002604 dh.perPonOnuIndicationChannel[intfID] = channels
2605 dh.perPonOnuIndicationChannelLock.Unlock()
2606 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002607 return channels.indicationChannel
2608
2609}
2610
Mahir Gunyelb0046752021-02-26 13:51:05 -08002611func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2612 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2613 dh.perPonOnuIndicationChannelLock.Lock()
2614 defer dh.perPonOnuIndicationChannelLock.Unlock()
2615 for _, v := range dh.perPonOnuIndicationChannel {
2616 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002617 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002618 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002619}
2620
Mahir Gunyelb0046752021-02-26 13:51:05 -08002621func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2622 ind := onuIndicationMsg{
2623 ctx: ctx,
2624 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002625 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002626 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002627 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002628 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002629}
2630
Mahir Gunyelb0046752021-02-26 13:51:05 -08002631func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002632 for {
2633 select {
2634 // process one indication per onu, before proceeding to the next one
2635 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08002636 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002637 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08002638 "ind": indication})
2639 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002640 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002641 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002642 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2643 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002644 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002645 }
2646 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002647 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002648 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2649 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002650 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002651 }
2652 }
2653 case <-onuChannels.stopChannel:
2654 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2655 close(onuChannels.indicationChannel)
2656 return
2657 }
2658 }
2659}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002660
2661// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2662// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04002663func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002664 if dh.getDeviceDeletionInProgressFlag() {
2665 // The device itself is going to be reset as part of deletion. So nothing to be done.
2666 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2667 return nil
2668 }
2669
Girish Gowdra491a9c62021-01-06 16:43:07 -08002670 // Step1 : Fill McastFlowOrGroupControlBlock
2671 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2672 // Step3 : Wait on response channel for response
2673 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002674 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002675 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2676 errChan := make(chan error)
2677 var groupID uint32
2678 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2679 ctx: ctx,
2680 flowOrGroupAction: action,
2681 flow: flow,
2682 group: group,
2683 errChan: &errChan,
2684 }
2685 if flow != nil {
2686 groupID = flow_utils.GetGroup(flow)
2687 } else if group != nil {
2688 groupID = group.Desc.GroupId
2689 } else {
2690 return errors.New("flow-and-group-both-nil")
2691 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002692 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2693 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2694 // Derive the appropriate go routine to handle the request by a simple module operation.
2695 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2696 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2697 // Wait for handler to return error value
2698 err := <-errChan
2699 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2700 return err
2701 }
2702 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2703 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002704}
2705
2706// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002707func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002708 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002709 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002710 // block on the channel to receive an incoming mcast flow/group
2711 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002712 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2713 if mcastFlowOrGroupCb.flow != nil {
2714 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2715 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2716 log.Fields{"device-id": dh.device.Id,
2717 "flowToAdd": mcastFlowOrGroupCb.flow})
2718 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2719 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2720 // Pass the return value over the return channel
2721 *mcastFlowOrGroupCb.errChan <- err
2722 } else { // flow remove
2723 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2724 log.Fields{"device-id": dh.device.Id,
2725 "flowToRemove": mcastFlowOrGroupCb.flow})
2726 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2727 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2728 // Pass the return value over the return channel
2729 *mcastFlowOrGroupCb.errChan <- err
2730 }
2731 } else { // mcast group
2732 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2733 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2734 log.Fields{"device-id": dh.device.Id,
2735 "groupToAdd": mcastFlowOrGroupCb.group})
2736 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2737 // Pass the return value over the return channel
2738 *mcastFlowOrGroupCb.errChan <- err
2739 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2740 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2741 log.Fields{"device-id": dh.device.Id,
2742 "groupToModify": mcastFlowOrGroupCb.group})
2743 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2744 // Pass the return value over the return channel
2745 *mcastFlowOrGroupCb.errChan <- err
2746 } else { // group remove
2747 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2748 log.Fields{"device-id": dh.device.Id,
2749 "groupToRemove": mcastFlowOrGroupCb.group})
2750 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2751 // Pass the return value over the return channel
2752 *mcastFlowOrGroupCb.errChan <- err
2753 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002754 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002755 case <-stopHandler:
2756 dh.mcastHandlerRoutineActive[routineIndex] = false
2757 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08002758 }
2759 }
2760}
kesavand62126212021-01-12 04:56:06 -05002761
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002762// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002763func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002764 for i, v := range dh.stopMcastHandlerRoutine {
2765 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002766 select {
2767 case v <- true:
2768 case <-time.After(time.Second * 5):
2769 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
2770 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002771 }
2772 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002773 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002774 logger.Debug(ctx, "stopped all mcast handler routines")
2775}
2776
kesavand62126212021-01-12 04:56:06 -05002777func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2778
2779 singleValResp := extension.SingleGetValueResponse{
2780 Response: &extension.GetValueResponse{
2781 Response: &extension.GetValueResponse_PortCoutners{
2782 PortCoutners: &extension.GetOltPortCountersResponse{},
2783 },
2784 },
2785 }
2786
2787 errResp := func(status extension.GetValueResponse_Status,
2788 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2789 return &extension.SingleGetValueResponse{
2790 Response: &extension.GetValueResponse{
2791 Status: status,
2792 ErrReason: reason,
2793 },
2794 }
2795 }
2796
2797 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2798 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2799 //send error response
2800 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2801 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2802 }
2803 statIndChn := make(chan bool, 1)
2804 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2805 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2806 //request openOlt agent to send the the port statistics indication
2807
2808 go func() {
2809 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2810 if err != nil {
2811 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2812 }
2813 }()
2814 select {
2815 case <-statIndChn:
2816 //indication received for ports stats
2817 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2818 case <-time.After(oltPortInfoTimeout * time.Second):
2819 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2820 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2821 case <-ctx.Done():
2822 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2823 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2824 }
2825 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2826 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002827 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05002828 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2829 cmnni := dh.portStats.collectNNIMetrics(intfID)
2830 if cmnni == nil {
2831 //TODO define the error reason
2832 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2833 }
2834 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2835 return &singleValResp
2836
2837 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2838 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002839 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05002840 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2841 cmpon := dh.portStats.collectPONMetrics(intfID)
2842 if cmpon == nil {
2843 //TODO define the error reason
2844 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2845 }
2846 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2847 return &singleValResp
2848 }
2849 }
2850 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2851}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302852
2853func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2854
2855 singleValResp := extension.SingleGetValueResponse{
2856 Response: &extension.GetValueResponse{
2857 Response: &extension.GetValueResponse_OnuPonCounters{
2858 OnuPonCounters: &extension.GetOnuCountersResponse{},
2859 },
2860 },
2861 }
2862
2863 errResp := func(status extension.GetValueResponse_Status,
2864 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2865 return &extension.SingleGetValueResponse{
2866 Response: &extension.GetValueResponse{
2867 Status: status,
2868 ErrReason: reason,
2869 },
2870 }
2871 }
2872 intfID := onuPonInfo.IntfId
2873 onuID := onuPonInfo.OnuId
2874 onuKey := dh.formOnuKey(intfID, onuID)
2875
2876 if _, ok := dh.onus.Load(onuKey); !ok {
2877 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2878 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2879 }
2880 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2881 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2882 if cmnni == nil {
2883 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2884 }
2885 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2886 return &singleValResp
2887
2888}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002889
2890func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2891
2892 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
2893 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
2894 if err != nil {
2895 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
2896 return generateSingleGetValueErrorResponse(err)
2897 }
2898 return &extension.SingleGetValueResponse{
2899 Response: &extension.GetValueResponse{
2900 Status: extension.GetValueResponse_OK,
2901 Response: &extension.GetValueResponse_RxPower{
2902 RxPower: &extension.GetRxPowerResponse{
2903 IntfId: rxPowerRequest.IntfId,
2904 OnuId: rxPowerRequest.OnuId,
2905 Status: rxPower.Status,
2906 FailReason: rxPower.FailReason.String(),
2907 RxPower: rxPower.RxPowerMeanDbm,
2908 },
2909 },
2910 },
2911 }
2912}
2913
2914func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
2915 errResp := func(status extension.GetValueResponse_Status,
2916 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2917 return &extension.SingleGetValueResponse{
2918 Response: &extension.GetValueResponse{
2919 Status: status,
2920 ErrReason: reason,
2921 },
2922 }
2923 }
2924
2925 if err != nil {
2926 if e, ok := status.FromError(err); ok {
2927 switch e.Code() {
2928 case codes.Internal:
2929 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2930 case codes.DeadlineExceeded:
2931 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2932 case codes.Unimplemented:
2933 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
2934 case codes.NotFound:
2935 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2936 }
2937 }
2938 }
2939
2940 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
2941}
khenaidoo106c61a2021-08-11 18:05:46 -04002942
2943/*
2944Helper functions to communicate with Core
2945*/
2946
2947func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
2948 cClient, err := dh.coreClient.GetCoreServiceClient()
2949 if err != nil || cClient == nil {
2950 return nil, err
2951 }
2952 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2953 defer cancel()
2954 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
2955}
2956
khenaidoodc2116e2021-10-19 17:33:19 -04002957func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04002958 cClient, err := dh.coreClient.GetCoreServiceClient()
2959 if err != nil || cClient == nil {
2960 return nil, err
2961 }
2962 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2963 defer cancel()
2964 return cClient.GetChildDevice(subCtx, childDeviceFilter)
2965}
2966
khenaidoodc2116e2021-10-19 17:33:19 -04002967func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04002968 cClient, err := dh.coreClient.GetCoreServiceClient()
2969 if err != nil || cClient == nil {
2970 return err
2971 }
2972 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2973 defer cancel()
2974 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
2975 return err
2976}
2977
2978func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
2979 cClient, err := dh.coreClient.GetCoreServiceClient()
2980 if err != nil || cClient == nil {
2981 return nil, err
2982 }
2983 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2984 defer cancel()
2985 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
2986}
2987
2988func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
2989 cClient, err := dh.coreClient.GetCoreServiceClient()
2990 if err != nil || cClient == nil {
2991 return nil, err
2992 }
2993 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
2994 defer cancel()
2995 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
2996}
2997
2998func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
2999 cClient, err := dh.coreClient.GetCoreServiceClient()
3000 if err != nil || cClient == nil {
3001 return err
3002 }
3003 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3004 defer cancel()
3005 _, err = cClient.DeviceUpdate(subCtx, device)
3006 return err
3007}
3008
khenaidoodc2116e2021-10-19 17:33:19 -04003009func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003010 cClient, err := dh.coreClient.GetCoreServiceClient()
3011 if err != nil || cClient == nil {
3012 return nil, err
3013 }
3014 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3015 defer cancel()
3016 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3017}
3018
khenaidoodc2116e2021-10-19 17:33:19 -04003019func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003020 cClient, err := dh.coreClient.GetCoreServiceClient()
3021 if err != nil || cClient == nil {
3022 return err
3023 }
3024 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3025 defer cancel()
3026 _, err = cClient.SendPacketIn(subCtx, pkt)
3027 return err
3028}
3029
3030func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3031 cClient, err := dh.coreClient.GetCoreServiceClient()
3032 if err != nil || cClient == nil {
3033 return err
3034 }
3035 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3036 defer cancel()
3037 _, err = cClient.PortCreated(subCtx, port)
3038 return err
3039}
3040
khenaidoodc2116e2021-10-19 17:33:19 -04003041func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003042 cClient, err := dh.coreClient.GetCoreServiceClient()
3043 if err != nil || cClient == nil {
3044 return err
3045 }
3046 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3047 defer cancel()
3048 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3049 return err
3050}
3051
khenaidoodc2116e2021-10-19 17:33:19 -04003052func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003053 cClient, err := dh.coreClient.GetCoreServiceClient()
3054 if err != nil || cClient == nil {
3055 return err
3056 }
3057 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3058 defer cancel()
3059 _, err = cClient.PortStateUpdate(subCtx, portState)
3060 return err
3061}
3062
khenaidoodc2116e2021-10-19 17:33:19 -04003063func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003064 cClient, err := dh.coreClient.GetCoreServiceClient()
3065 if err != nil || cClient == nil {
3066 return nil, err
3067 }
3068 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3069 defer cancel()
3070 return cClient.GetDevicePort(subCtx, portFilter)
3071}
3072
3073/*
3074Helper functions to communicate with child adapter
3075*/
3076
khenaidoodc2116e2021-10-19 17:33:19 -04003077func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003078 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3079 if err != nil || aClient == nil {
3080 return err
3081 }
3082 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3083 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3084 defer cancel()
3085 _, err = aClient.OmciIndication(subCtx, response)
3086 return err
3087}
3088
khenaidoodc2116e2021-10-19 17:33:19 -04003089func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003090 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3091 if err != nil || aClient == nil {
3092 return err
3093 }
3094 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3095 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3096 defer cancel()
3097 _, err = aClient.OnuIndication(subCtx, onuInd)
3098 return err
3099}
3100
khenaidoodc2116e2021-10-19 17:33:19 -04003101func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003102 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3103 if err != nil || aClient == nil {
3104 return err
3105 }
3106 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3107 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3108 defer cancel()
3109 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3110 return err
3111}
3112
khenaidoodc2116e2021-10-19 17:33:19 -04003113func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003114 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3115 if err != nil || aClient == nil {
3116 return err
3117 }
3118 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3119 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3120 defer cancel()
3121 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3122 return err
3123}
3124
khenaidoodc2116e2021-10-19 17:33:19 -04003125func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003126 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3127 if err != nil || aClient == nil {
3128 return err
3129 }
3130 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3131 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3132 defer cancel()
3133 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3134 return err
3135}
3136
3137/*
3138Helper functions for remote communication
3139*/
3140
3141// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3142// supports is deleted
3143func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3144 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3145
3146 dh.lockChildAdapterClients.Lock()
3147 defer dh.lockChildAdapterClients.Unlock()
3148 if _, ok := dh.childAdapterClients[endpoint]; ok {
3149 // Already set
3150 return nil
3151 }
3152
3153 // Setup child's adapter grpc connection
3154 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003155 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3156 dh.cfg.AdapterEndpoint,
3157 endpoint,
3158 dh.onuAdapterRestarted); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003159 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3160 return err
3161 }
khenaidoo27e7ac92021-12-08 14:43:09 -05003162 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.setAndTestOnuInterAdapterServiceHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003163
3164 // Wait until we have a connection to the child adapter.
3165 // Unlimited retries or until context expires
3166 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3167 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3168 for {
3169 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3170 if err == nil && client != nil {
3171 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3172 break
3173 }
3174 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3175 // Backoff
3176 if err = backoff.Backoff(subCtx); err != nil {
3177 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3178 break
3179 }
3180 }
3181 return nil
3182}
3183
khenaidoodc2116e2021-10-19 17:33:19 -04003184func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003185
3186 // First check from cache
3187 dh.lockChildAdapterClients.RLock()
3188 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3189 dh.lockChildAdapterClients.RUnlock()
3190 return cgClient.GetOnuInterAdapterServiceClient()
3191 }
3192 dh.lockChildAdapterClients.RUnlock()
3193
3194 // Set the child connection - can occur on restarts
3195 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3196 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3197 cancel()
3198 if err != nil {
3199 return nil, err
3200 }
3201
3202 // Get the child client now
3203 dh.lockChildAdapterClients.RLock()
3204 defer dh.lockChildAdapterClients.RUnlock()
3205 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3206 return cgClient.GetOnuInterAdapterServiceClient()
3207 }
3208 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3209}
3210
3211func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3212 dh.lockChildAdapterClients.Lock()
3213 defer dh.lockChildAdapterClients.Unlock()
3214 for key, client := range dh.childAdapterClients {
3215 client.Stop(ctx)
3216 delete(dh.childAdapterClients, key)
3217 }
3218}
3219
3220// TODO: Any action the adapter needs to do following a onu adapter restart?
3221func (dh *DeviceHandler) onuAdapterRestarted(ctx context.Context, endPoint string) error {
khenaidoo7eb2d672021-10-22 19:08:50 -04003222 logger.Warnw(ctx, "onu-adapter-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003223 return nil
3224}
3225
khenaidoo27e7ac92021-12-08 14:43:09 -05003226// setAndTestOnuInterAdapterServiceHandler is used to test whether the remote gRPC service is up
3227func (dh *DeviceHandler) setAndTestOnuInterAdapterServiceHandler(ctx context.Context, conn *grpc.ClientConn, clientConn *common.Connection) interface{} {
3228 // The onu adapter needs to know whether the olt adapter can connect to it. Since the olt adapter
3229 // has a grpc client connection per device handler (i.e. per olt device) to the onu adapter
3230 // then the onu adapter needs to know whether that specific client can connect to it. Because the
3231 // client uses a polling mechanism then not all grpc clients could be connected at the same time,
3232 // a maximum difference of 5 sec. We therefore add the parent device as additional contextual information
3233 // to this request.
3234 dh.lockDevice.RLock()
3235 if dh.device != nil {
3236 clientConn.ContextInfo = dh.device.Id
3237 }
3238 dh.lockDevice.RUnlock()
khenaidoodc2116e2021-10-19 17:33:19 -04003239 svc := onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo27e7ac92021-12-08 14:43:09 -05003240 if h, err := svc.GetHealthStatus(ctx, clientConn); err != nil || h.State != health.HealthStatus_HEALTHY {
khenaidoo106c61a2021-08-11 18:05:46 -04003241 return nil
3242 }
3243 return svc
3244}
Girish Gowdra950326e2021-11-05 12:43:24 -07003245
3246func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3247 dh.lockDevice.Lock()
3248 defer dh.lockDevice.Unlock()
3249 dh.isDeviceDeletionInProgress = flag
3250}
3251
3252func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3253 dh.lockDevice.RLock()
3254 defer dh.lockDevice.RUnlock()
3255 return dh.isDeviceDeletionInProgress
3256}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003257
3258// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3259// Returns false if waiting timed out.
3260func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3261 c := make(chan struct{})
3262 go func() {
3263 defer close(c)
3264 wg.Wait()
3265 }()
3266 select {
3267 case <-c:
3268 return true // completed normally
3269 case <-time.After(timeout):
3270 return false // timed out
3271 }
3272}