blob: 8248278e2b1f08644f84e5fbc8bd25c0ee015d6f [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"
Girish Gowdra0f3190e2022-02-11 14:18:28 -080026 "github.com/opencord/voltha-lib-go/v7/pkg/db"
27 "github.com/opencord/voltha-lib-go/v7/pkg/db/kvstore"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040029 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070030 "strconv"
31 "strings"
32 "sync"
33 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053034
khenaidoo106c61a2021-08-11 18:05:46 -040035 vgrpc "github.com/opencord/voltha-lib-go/v7/pkg/grpc"
khenaidoo106c61a2021-08-11 18:05:46 -040036
Matteo Scandolo945e4012019-12-12 14:16:11 -080037 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070038 "github.com/gogo/protobuf/proto"
Girish Kumar93e91742020-07-27 16:43:19 +000039 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
40 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
khenaidoo106c61a2021-08-11 18:05:46 -040041 "github.com/opencord/voltha-lib-go/v7/pkg/config"
42 "github.com/opencord/voltha-lib-go/v7/pkg/events/eventif"
43 flow_utils "github.com/opencord/voltha-lib-go/v7/pkg/flows"
44 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070045 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040046 "github.com/opencord/voltha-lib-go/v7/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080047
khenaidoo106c61a2021-08-11 18:05:46 -040048 conf "github.com/opencord/voltha-openolt-adapter/internal/pkg/config"
Thomas Lee S94109f12020-03-03 16:39:29 +053049 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080050 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040051 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040052 ca "github.com/opencord/voltha-protos/v5/go/core_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040053 "github.com/opencord/voltha-protos/v5/go/extension"
khenaidoodc2116e2021-10-19 17:33:19 -040054 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
55 "github.com/opencord/voltha-protos/v5/go/onu_inter_adapter_service"
khenaidoo106c61a2021-08-11 18:05:46 -040056 of "github.com/opencord/voltha-protos/v5/go/openflow_13"
57 oop "github.com/opencord/voltha-protos/v5/go/openolt"
58 "github.com/opencord/voltha-protos/v5/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070059 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040060 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040061 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053062)
63
salmansiddiqui7ac62132019-08-22 03:58:50 +000064// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040065const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080066 InvalidPort = 0xffffffff
67 MaxNumOfGroupHandlerChannels = 256
68
69 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
70 McastFlowOrGroupModify = "McastFlowOrGroupModify"
71 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050072 oltPortInfoTimeout = 3
Elia Battiston596406d2022-02-02 12:19:00 +010073
74 defaultPortSpeedMbps = 1000
Manikkaraj kb1d51442019-07-23 10:41:02 -040075)
76
Phaneendra Manda4c62c802019-03-06 21:37:49 +053077//DeviceHandler will interact with the OLT device.
78type DeviceHandler struct {
khenaidoo106c61a2021-08-11 18:05:46 -040079 cm *config.ConfigManager
80 device *voltha.Device
81 cfg *conf.AdapterFlags
82 coreClient *vgrpc.Client
83 childAdapterClients map[string]*vgrpc.Client
84 lockChildAdapterClients sync.RWMutex
85 EventProxy eventif.EventProxy
86 openOLT *OpenOLT
khenaidooefff76e2021-12-15 16:51:30 -050087 exitChannel chan struct{}
khenaidoo106c61a2021-08-11 18:05:46 -040088 lockDevice sync.RWMutex
89 Client oop.OpenoltClient
90 transitionMap *TransitionMap
91 clientCon *grpc.ClientConn
92 flowMgr []*OpenOltFlowMgr
93 groupMgr *OpenOltGroupMgr
94 eventMgr *OpenOltEventMgr
95 resourceMgr []*rsrcMgr.OpenOltResourceMgr
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070096
97 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053098
Girish Gowdra3ab6d212020-03-24 17:33:15 -070099 discOnus sync.Map
100 onus sync.Map
101 portStats *OpenOltStatisticsMgr
102 metrics *pmmetrics.PmMetrics
103 stopCollector chan bool
104 stopHeartbeatCheck chan bool
105 activePorts sync.Map
106 stopIndications chan bool
107 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700108
Mahir Gunyelb0046752021-02-26 13:51:05 -0800109 totalPonPorts uint32
110 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
111 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800112
113 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
114 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700115 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
116 stopMcastHandlerRoutine []chan bool
117 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000118
119 adapterPreviouslyConnected bool
120 agentPreviouslyConnected bool
Girish Gowdra950326e2021-11-05 12:43:24 -0700121
122 isDeviceDeletionInProgress bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700123}
124
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700125//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700126type OnuDevice struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400127 deviceID string
128 deviceType string
129 serialNumber string
130 onuID uint32
131 intfID uint32
132 proxyDeviceID string
133 losRaised bool
134 rdiRaised bool
135 adapterEndpoint string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700136}
137
Mahir Gunyelb0046752021-02-26 13:51:05 -0800138type onuIndicationMsg struct {
139 ctx context.Context
140 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800141}
142
143type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800144 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800145 stopChannel chan struct{}
146}
147
Girish Gowdra491a9c62021-01-06 16:43:07 -0800148//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
149//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
150//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
151//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
152type McastFlowOrGroupControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400153 ctx context.Context // Flow/group handler context
154 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
155 flow *of.OfpFlowStats // Flow message (can be nil or valid flow)
156 group *of.OfpGroupEntry // Group message (can be nil or valid group)
157 errChan *chan error // channel to report the mcast Flow/group handling error
Girish Gowdra491a9c62021-01-06 16:43:07 -0800158}
159
Naga Manjunath7615e552019-10-11 22:35:47 +0530160var pmNames = []string{
161 "rx_bytes",
162 "rx_packets",
163 "rx_mcast_packets",
164 "rx_bcast_packets",
165 "tx_bytes",
166 "tx_packets",
167 "tx_mcast_packets",
168 "tx_bcast_packets",
169}
170
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700171//NewOnuDevice creates a new Onu Device
khenaidoo106c61a2021-08-11 18:05:46 -0400172func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool, adapterEndpoint string) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700173 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700174 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700175 device.deviceType = deviceTp
176 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700177 device.onuID = onuID
178 device.intfID = intfID
179 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530180 device.losRaised = losRaised
khenaidoo106c61a2021-08-11 18:05:46 -0400181 device.adapterEndpoint = adapterEndpoint
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700182 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530183}
184
185//NewDeviceHandler creates a new device handler
khenaidoo106c61a2021-08-11 18:05:46 -0400186func NewDeviceHandler(cc *vgrpc.Client, ep eventif.EventProxy, device *voltha.Device, adapter *OpenOLT, cm *config.ConfigManager, cfg *conf.AdapterFlags) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700187 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800188 dh.cm = cm
khenaidoo106c61a2021-08-11 18:05:46 -0400189 dh.coreClient = cc
Devmalya Paulfb990a52019-07-09 10:01:49 -0400190 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700191 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700192 dh.device = cloned
193 dh.openOLT = adapter
khenaidooefff76e2021-12-15 16:51:30 -0500194 dh.exitChannel = make(chan struct{})
cuilin20187b2a8c32019-03-26 19:52:28 -0700195 dh.lockDevice = sync.RWMutex{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800196 dh.stopCollector = make(chan bool, 2) // TODO: Why buffered?
197 dh.stopHeartbeatCheck = make(chan bool, 2) // TODO: Why buffered?
Naga Manjunath7615e552019-10-11 22:35:47 +0530198 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500199 dh.activePorts = sync.Map{}
Girish Gowdraae56c722021-11-22 14:31:11 -0800200 dh.stopIndications = make(chan bool, 1) // TODO: Why buffered?
Mahir Gunyelb0046752021-02-26 13:51:05 -0800201 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
khenaidoo106c61a2021-08-11 18:05:46 -0400202 dh.childAdapterClients = make(map[string]*vgrpc.Client)
203 dh.cfg = cfg
Girish Gowdra491a9c62021-01-06 16:43:07 -0800204 // Create a slice of buffered channels for handling concurrent mcast flow/group.
205 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700206 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
207 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800208 for i := range dh.incomingMcastFlowOrGroup {
209 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdraae56c722021-11-22 14:31:11 -0800210 dh.stopMcastHandlerRoutine[i] = make(chan bool)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800211 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
212 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
213 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
214 // for incoming mcast flow/group to be processed serially.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700215 dh.mcastHandlerRoutineActive[i] = true
216 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800217 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700218 //TODO initialize the support classes.
219 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530220}
221
222// start save the device to the data model
223func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700224 dh.lockDevice.Lock()
225 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000226 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700227 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000228 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530229}
230
khenaidooefff76e2021-12-15 16:51:30 -0500231// Stop stops the device handler
232func (dh *DeviceHandler) Stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700233 dh.lockDevice.Lock()
234 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000235 logger.Debug(ctx, "stopping-device-agent")
khenaidooefff76e2021-12-15 16:51:30 -0500236 close(dh.exitChannel)
khenaidoo106c61a2021-08-11 18:05:46 -0400237
khenaidooefff76e2021-12-15 16:51:30 -0500238 // Delete (which will stop also) all grpc connections to the child adapters
239 dh.deleteAdapterClients(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000240 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530241}
242
ssiddiqui04386ee2021-08-23 21:58:25 +0530243func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
244 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
245 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
246 if pooledIntfID == intfID {
247 return resourceRanges.GetTechnology()
248 }
249 }
250 }
251 return ""
252}
253
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400254func macifyIP(ip net.IP) string {
255 if len(ip) > 0 {
256 oct1 := strconv.FormatInt(int64(ip[12]), 16)
257 oct2 := strconv.FormatInt(int64(ip[13]), 16)
258 oct3 := strconv.FormatInt(int64(ip[14]), 16)
259 oct4 := strconv.FormatInt(int64(ip[15]), 16)
260 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
261 }
262 return ""
263}
264
Neha Sharma96b7bf22020-06-15 10:37:32 +0000265func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400266 var genmac string
267 var addr net.IP
268 var ips []string
269 var err error
270
Neha Sharma96b7bf22020-06-15 10:37:32 +0000271 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400272
273 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000274 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400275
276 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000277 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400278 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000279 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400280 }
281 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000282 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530283 log.Fields{"host": ips[0],
284 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400285 return genmac, nil
286 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000287 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400288 }
289
290 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000291 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530292 log.Fields{"host": host,
293 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400294 return genmac, nil
295}
296
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530297func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700298 slist := strings.Split(mac, ":")
299 result := make([]uint32, len(slist))
300 var err error
301 var tmp int64
302 for index, val := range slist {
303 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
304 return []uint32{1, 2, 3, 4, 5, 6}
305 }
306 result[index] = uint32(tmp)
307 }
308 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530309}
310
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700311//GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800312func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530313
David K. Bainbridge794735f2020-02-11 21:01:37 -0800314 switch portType {
315 case voltha.Port_ETHERNET_NNI:
316 return fmt.Sprintf("nni-%d", portNum), nil
317 case voltha.Port_PON_OLT:
318 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700319 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800320
Girish Kumarf26e4882020-03-05 06:49:10 +0000321 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530322}
323
Elia Battiston596406d2022-02-02 12:19:00 +0100324func makeOfpPort(macAddress string, speedMbps uint32) *of.OfpPort {
325 if speedMbps == 0 {
326 //In case it was not set in the indication
327 //and no other value was provided
328 speedMbps = defaultPortSpeedMbps
329 }
330
331 ofpPortSpeed := of.OfpPortFeatures_OFPPF_OTHER
332 switch speedMbps {
333 case 1000000:
334 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1TB_FD
335 case 100000:
336 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100GB_FD
337 case 40000:
338 ofpPortSpeed = of.OfpPortFeatures_OFPPF_40GB_FD
339 case 10000:
340 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10GB_FD
341 case 1000:
342 ofpPortSpeed = of.OfpPortFeatures_OFPPF_1GB_FD
343 case 100:
344 ofpPortSpeed = of.OfpPortFeatures_OFPPF_100MB_FD
345 case 10:
346 ofpPortSpeed = of.OfpPortFeatures_OFPPF_10MB_FD
347 }
348
349 capacity := uint32(ofpPortSpeed | of.OfpPortFeatures_OFPPF_FIBER)
350
351 port := &of.OfpPort{
352 HwAddr: macAddressToUint32Array(macAddress),
353 Config: 0,
354 State: uint32(of.OfpPortState_OFPPS_LIVE),
355 Curr: capacity,
356 Advertised: capacity,
357 Peer: capacity,
358 CurrSpeed: speedMbps * 1000, //kbps
359 MaxSpeed: speedMbps * 1000, //kbps
360 }
361
362 return port
363}
364
365func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string, speedMbps uint32) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000366 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700367 if state == "up" {
368 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500369 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500370 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700371 } else {
372 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500373 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700374 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700375 portNum := plt.IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400376 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800377 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000378 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400379 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500380
khenaidoo106c61a2021-08-11 18:05:46 -0400381 // Check if port exists
khenaidoodc2116e2021-10-19 17:33:19 -0400382 port, err := dh.getPortFromCore(ctx, &ca.PortFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400383 DeviceId: dh.device.Id,
384 Port: portNum,
385 })
386 if err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000387 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
khenaidoodc2116e2021-10-19 17:33:19 -0400388 err = dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -0400389 DeviceId: dh.device.Id,
390 PortType: portType,
391 PortNo: portNum,
392 OperStatus: operStatus})
393 if err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400394 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
395 "device-id": dh.device.Id,
396 "port-type": portType,
397 "port-number": portNum,
398 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500399 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400400 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500401 }
khenaidoo106c61a2021-08-11 18:05:46 -0400402
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400403 // Now create Port
khenaidoo106c61a2021-08-11 18:05:46 -0400404 port = &voltha.Port{
405 DeviceId: dh.device.Id,
cuilin20187b2a8c32019-03-26 19:52:28 -0700406 PortNo: portNum,
407 Label: label,
408 Type: portType,
409 OperStatus: operStatus,
Elia Battiston596406d2022-02-02 12:19:00 +0100410 OfpPort: makeOfpPort(dh.device.MacAddress, speedMbps),
cuilin20187b2a8c32019-03-26 19:52:28 -0700411 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000412 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700413 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -0400414 err = dh.createPortInCore(ctx, port)
415 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000416 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800417 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000418 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400419 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000420 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530421 return nil
422}
423
Kent Hagermane6ff1012020-07-14 15:07:53 -0400424func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -0400425 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530426 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400427 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
428 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530429 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800430 dh.lockDevice.Lock()
431 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530432 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530433}
434
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700435// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530436// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800437func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000438 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700439 defer func() {
440 dh.lockDevice.Lock()
441 dh.isReadIndicationRoutineActive = false
442 dh.lockDevice.Unlock()
443 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700444 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700445 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700446 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700447 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400448
David Bainbridgef5879ca2019-12-13 21:17:54 +0000449 // Create an exponential backoff around re-enabling indications. The
450 // maximum elapsed time for the back off is set to 0 so that we will
451 // continue to retry. The max interval defaults to 1m, but is set
452 // here for code clarity
453 indicationBackoff := backoff.NewExponentialBackOff()
454 indicationBackoff.MaxElapsedTime = 0
455 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700456
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700457 dh.lockDevice.Lock()
458 dh.isReadIndicationRoutineActive = true
459 dh.lockDevice.Unlock()
460
Girish Gowdra3f974912020-03-23 20:35:18 -0700461Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700462 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400463 select {
464 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000465 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700466 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400467 default:
468 indication, err := indications.Recv()
469 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000470 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530471 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530472 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400473 // Use an exponential back off to prevent getting into a tight loop
474 duration := indicationBackoff.NextBackOff()
475 if duration == backoff.Stop {
476 // If we reach a maximum then warn and reset the backoff
477 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000478 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530479 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530480 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400481 indicationBackoff.Reset()
482 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700483
484 // On failure process a backoff timer while watching for stopIndications
485 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700486 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700487 select {
488 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000489 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700490 if !backoffTimer.Stop() {
491 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700492 }
493 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700494 case <-backoffTimer.C:
495 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700496 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700497 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
498 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400499 }
500 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000501 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530502 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000503 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530504 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530505 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700506 // Close the stream, and re-initialize it
507 if err = indications.CloseSend(); err != nil {
508 // Ok to ignore here, because we landed here due to a problem on the stream
509 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000510 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530511 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530512 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700513 }
Matteo Scandolof16389e2021-05-18 00:47:08 +0000514 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700515 return err
516 }
517 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400518 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530519 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400520 // Reset backoff if we have a successful receive
521 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400522 // When OLT is admin down, ignore all indications.
Girish Gowdra852ad912021-05-04 00:05:50 -0700523 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000524 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530525 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530526 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400527 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400528 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400529 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700530 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700531 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700532 // Close the send stream
533 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700534
Girish Gowdra3f974912020-03-23 20:35:18 -0700535 return nil
536}
537
538func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700539 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700540 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
541 if err != nil {
542 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
543 }
544 if indications == nil {
545 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
546 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700547 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700548 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400549}
550
551// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
552func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
553 switch indication.Data.(type) {
554 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
555 return true
556
557 default:
558 return false
559 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700560}
561
David K. Bainbridge794735f2020-02-11 21:01:37 -0800562func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700563 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000564 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530565 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700566 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530567 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700568 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000569 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000570 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530571 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000572 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800573 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000574 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800575 }
576 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577}
578
David K. Bainbridge794735f2020-02-11 21:01:37 -0800579// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530580func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700581 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700582 switch indication.Data.(type) {
583 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000584 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
585 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700586 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 -0800587 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400588 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800589 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700590 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000591 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
592 defer span.Finish()
593
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700594 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800595 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100596 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400597 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800598 }
599 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000600 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700601 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000602 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
603 defer span.Finish()
604
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 intfOperInd := indication.GetIntfOperInd()
606 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800607 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100608 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState(), intfOperInd.GetSpeed()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400609 _ = 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 -0800610 }
611 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700612 } else if intfOperInd.GetType() == "pon" {
613 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
614 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800615 go func() {
Elia Battiston596406d2022-02-02 12:19:00 +0100616 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState(), defaultPortSpeedMbps); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400617 _ = 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 -0800618 }
619 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000620 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700621 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000622 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530623 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530624 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700625 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000626 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
627 defer span.Finish()
628
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700629 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000630 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800631 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800632 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000634 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
635 defer span.Finish()
636
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700637 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000638 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800639 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800640 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700641 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000642 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
643 defer span.Finish()
644
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700645 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000646 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 -0800647 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000648 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400649 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800650 }
651 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700652 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000653 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
654 defer span.Finish()
655
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000657 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700658 "intf-type": pktInd.IntfId,
659 "intf-id": pktInd.IntfId,
660 "gem-port-id": pktInd.GemportId,
661 "port-no": pktInd.PortNo,
662 "device-id": dh.device.Id,
663 })
664
665 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000666 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700667 "intf-type": pktInd.IntfId,
668 "intf-id": pktInd.IntfId,
669 "gem-port-id": pktInd.GemportId,
670 "port-no": pktInd.PortNo,
671 "packet": hex.EncodeToString(pktInd.Pkt),
672 "device-id": dh.device.Id,
673 })
674 }
675
David K. Bainbridge794735f2020-02-11 21:01:37 -0800676 go func() {
677 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400678 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800679 }
680 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700681 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000682 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
683 defer span.Finish()
684
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700685 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700686 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700687 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000688 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
689 defer span.Finish()
690
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700691 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000692 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700693 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000694 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
695 defer span.Finish()
696
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700697 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000698 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
699 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700700 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530701}
702
703// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530704func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530705 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000706 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530707
Girish Gowdra618fa572021-09-01 17:19:29 -0700708 // instantiate the mcast handler routines.
709 for i := range dh.incomingMcastFlowOrGroup {
710 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
711 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
712 if !dh.mcastHandlerRoutineActive[i] {
713 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
714 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
715 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
716 // for incoming mcast flow/group to be processed serially.
717 dh.mcastHandlerRoutineActive[i] = true
718 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
719 }
720 }
721
Girish Gowdru0c588b22019-04-23 23:24:56 -0400722 // Synchronous call to update device state - this method is run in its own go routine
khenaidoodc2116e2021-10-19 17:33:19 -0400723 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400724 DeviceId: dh.device.Id,
725 OperStatus: voltha.OperStatus_ACTIVE,
726 ConnStatus: voltha.ConnectStatus_REACHABLE,
727 }); err != nil {
728 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400729 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000730
731 //Clear olt communication failure event
732 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
733 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700734 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000735 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
736
Gamze Abakac2c32a62021-03-11 11:44:18 +0000737 //check adapter and agent reconcile status
738 //reboot olt if needed (olt disconnection case)
739 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
740 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
741 log.Fields{
742 "device-id": dh.device.Id,
743 "adapter-status": dh.adapterPreviouslyConnected,
744 "agent-status": dh.agentPreviouslyConnected,
745 })
746 _ = dh.RebootDevice(ctx, dh.device)
747 }
748
Girish Gowdru0c588b22019-04-23 23:24:56 -0400749 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530750}
751
752// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530753func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000754 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400755
khenaidoo106c61a2021-08-11 18:05:46 -0400756 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400757 if err != nil || device == nil {
758 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000759 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400760 }
761
762 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400763
764 //Update the device oper state and connection status
765 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800766 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400767 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800768 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400769
khenaidoodc2116e2021-10-19 17:33:19 -0400770 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400771 DeviceId: cloned.Id,
772 OperStatus: cloned.OperStatus,
773 ConnStatus: cloned.ConnectStatus,
774 }); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000775 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400776 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400777
778 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -0400779 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400780 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000781 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400782 }
783 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400784 // Update onu state as down in onu adapter
785 onuInd := oop.OnuIndication{}
786 onuInd.OperState = "down"
khenaidoo106c61a2021-08-11 18:05:46 -0400787
788 ogClient, err := dh.getChildAdapterServiceClient(onuDevice.AdapterEndpoint)
789 if err != nil {
790 return err
791 }
792 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
khenaidoodc2116e2021-10-19 17:33:19 -0400793 _, err = ogClient.OnuIndication(subCtx, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -0400794 DeviceId: onuDevice.Id,
795 OnuIndication: &onuInd,
796 })
797 cancel()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800798 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400799 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -0400800 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800801 "onu-indicator": onuInd,
802 "device-type": onuDevice.Type,
803 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700804 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800805 } else {
806 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 -0700807 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400808 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800809 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700810 /* Discovered ONUs entries need to be cleared , since after OLT
811 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530812 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800813 dh.lockDevice.Unlock()
814
Neha Sharma96b7bf22020-06-15 10:37:32 +0000815 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700816 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530817}
818
819// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530820func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400821 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000822
823 // if the connection is already available, close the previous connection (olt reboot case)
824 if dh.clientCon != nil {
825 if err = dh.clientCon.Close(); err != nil {
826 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
827 } else {
828 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
829 }
830 }
831
832 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000833 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
834 grpc.WithInsecure(),
835 grpc.WithBlock(),
836 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000837 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000838 )),
839 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000840 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000841 )))
842
843 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530844 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530845 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000846 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400847 }
848 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530849}
850
851// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530852func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400853 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530854 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400855 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530856}
857
858// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530859func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530860 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000861 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400862
863 // Case where OLT is disabled and then rebooted.
khenaidoo106c61a2021-08-11 18:05:46 -0400864 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Thomas Lee S985938d2020-05-04 11:40:41 +0530865 if err != nil || device == nil {
866 /*TODO: needs to handle error scenarios */
867 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
868 }
869 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000870 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400871
872 cloned := proto.Clone(device).(*voltha.Device)
873 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
874 cloned.OperStatus = voltha.OperStatus_UNKNOWN
875 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -0400876
khenaidoodc2116e2021-10-19 17:33:19 -0400877 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -0400878 DeviceId: cloned.Id,
879 OperStatus: cloned.OperStatus,
880 ConnStatus: cloned.ConnectStatus,
881 }); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530882 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 -0400883 }
884
Chaitrashree G S44124192019-08-07 20:21:36 -0400885 // 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 +0530886 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400887 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530888 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400889 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400890 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
891 // all the modules initialized and ready to handle incoming ONUs.
892
Thomas Lee S985938d2020-05-04 11:40:41 +0530893 err = dh.initializeDeviceHandlerModules(ctx)
894 if err != nil {
895 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 -0400896 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400897
898 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800899 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530900 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400901 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800902 }
903 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700904
905 go startHeartbeatCheck(ctx, dh)
906
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400907 return nil
908 }
909
khenaidoo106c61a2021-08-11 18:05:46 -0400910 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400911 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400912 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400913 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400914 }
khenaidoo106c61a2021-08-11 18:05:46 -0400915 dh.populateActivePorts(ctx, ports.Items)
916 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400917 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400918 }
919
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400920 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530921 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 -0400922 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530923
cuilin20187b2a8c32019-03-26 19:52:28 -0700924 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800925 go func() {
926 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400927 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800928 }
929 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000930 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000931
932 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000933 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000934 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700935
936 go startHeartbeatCheck(ctx, dh)
937
cuilin20187b2a8c32019-03-26 19:52:28 -0700938 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530939}
940
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400941func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700942 var err error
943 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400944
945 if err != nil {
946 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
947 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700948 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
949 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
yasin saplid0566272021-12-21 09:10:30 +0000950 // +1 is for NNI
951 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts+1)
952 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts+1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700953 var i uint32
yasin saplid0566272021-12-21 09:10:30 +0000954 // Index from 0 to until totalPonPorts ( Ex: 0 .. 15 ) -> PonPort Managers
955 // Index totalPonPorts ( Ex: 16 ) -> NniPort Manager
956 // There is only one NNI manager since multiple NNI is not supported for now
957 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700958 // Instantiate resource manager
959 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 -0700960 return olterrors.ErrResourceManagerInstantiating
961 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400962 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700963 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
964 // the KV store to manage mcast group data. Provide the first instance (0th index)
965 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
966 return olterrors.ErrGroupManagerInstantiating
967 }
yasin saplid0566272021-12-21 09:10:30 +0000968 for i = 0; i < dh.totalPonPorts+1; i++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700969 // Instantiate flow manager
970 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
971 return olterrors.ErrFlowManagerInstantiating
972 }
Girish Gowdra76a1b092021-07-28 10:07:04 -0700973 dh.resourceMgr[i].TechprofileRef = dh.flowMgr[i].techprofile
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700974 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400975 /* TODO: Instantiate Alarm , stats , BW managers */
976 /* Instantiating Event Manager to handle Alarms and KPIs */
977 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
978
979 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000980 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400981
982 return nil
983
984}
985
Neha Sharma96b7bf22020-06-15 10:37:32 +0000986func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400987 var err error
988 var deviceInfo *oop.DeviceInfo
989
Neha Sharma8f4e4322020-08-06 10:51:53 +0000990 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400991
992 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000993 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400994 }
995 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000996 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400997 }
998
Neha Sharma96b7bf22020-06-15 10:37:32 +0000999 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001000 dh.device.Root = true
1001 dh.device.Vendor = deviceInfo.Vendor
1002 dh.device.Model = deviceInfo.Model
1003 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
1004 dh.device.HardwareVersion = deviceInfo.HardwareVersion
1005 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
1006
1007 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001008 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001009 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +00001010 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001011 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001012 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001013 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001014 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001015 dh.device.MacAddress = genmac
1016 } else {
1017 dh.device.MacAddress = deviceInfo.DeviceId
1018 }
1019
1020 // Synchronous call to update device - this method is run in its own go routine
khenaidoo106c61a2021-08-11 18:05:46 -04001021 if err = dh.updateDeviceInCore(ctx, dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001022 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -04001023 }
1024
1025 return deviceInfo, nil
1026}
1027
Neha Sharma96b7bf22020-06-15 10:37:32 +00001028func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07001029 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301030 for {
1031 select {
1032 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +00001033 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +05301034 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001035 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -07001036
khenaidoo106c61a2021-08-11 18:05:46 -04001037 ports, err := dh.listDevicePortsFromCore(ctx, dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001038 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001039 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001040 continue
1041 }
khenaidoo106c61a2021-08-11 18:05:46 -04001042 for _, port := range ports.Items {
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301043 // NNI Stats
1044 if port.Type == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001045 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301046 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001047 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001048 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001049 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301050 }
1051 // PON Stats
1052 if port.Type == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001053 intfID := plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301054 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
1055 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001056 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001057 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +05301058 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001059 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001060
yasin sapli9e4c5092022-02-01 13:52:33 +00001061 onuGemInfoLst := dh.resourceMgr[intfID].GetOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001062 if len(onuGemInfoLst) > 0 {
1063 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +00001064 }
Chaitrashree G Sef088112020-02-03 21:39:27 -05001065 }
Naga Manjunath7615e552019-10-11 22:35:47 +05301066 }
1067 }
1068 }
1069}
1070
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001071//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +05301072func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001073 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001074 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +05301075 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +05301076
1077 // Now, set the initial PM configuration for that device
khenaidoo106c61a2021-08-11 18:05:46 -04001078 cgClient, err := dh.coreClient.GetCoreServiceClient()
1079 if err != nil {
1080 logger.Errorw(ctx, "no-core-connection", log.Fields{"device-id": dh.device.Id, "error": err})
1081 return
1082 }
1083
1084 // Now, set the initial PM configuration for that device
1085 if _, err := cgClient.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001086 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +05301087 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301088}
1089
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001090//GetOfpDeviceInfo Gets the Ofp information of the given device
khenaidoodc2116e2021-10-19 17:33:19 -04001091func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ca.SwitchCapability, error) {
1092 return &ca.SwitchCapability{
cuilin20187b2a8c32019-03-26 19:52:28 -07001093 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301094 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001095 HwDesc: "open_pon",
1096 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001097 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001098 },
1099 SwitchFeatures: &of.OfpSwitchFeatures{
1100 NBuffers: 256,
1101 NTables: 2,
1102 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1103 of.OfpCapabilities_OFPC_TABLE_STATS |
1104 of.OfpCapabilities_OFPC_PORT_STATS |
1105 of.OfpCapabilities_OFPC_GROUP_STATS),
1106 },
1107 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301108}
1109
khenaidoo106c61a2021-08-11 18:05:46 -04001110// GetTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
khenaidoodc2116e2021-10-19 17:33:19 -04001111func (dh *DeviceHandler) GetTechProfileDownloadMessage(ctx context.Context, request *ia.TechProfileInstanceRequestMessage) (*ia.TechProfileDownloadMessage, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001112 ifID, err := plt.IntfIDFromPonPortNum(ctx, request.ParentPonPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001113 if err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001114 return nil, err
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001115 }
khenaidoo106c61a2021-08-11 18:05:46 -04001116 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, request.TpInstancePath, request.OnuId, request.DeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001117}
1118
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001120 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 -07001121 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001122 var deviceID string
1123 var proxyDeviceID string
khenaidoo106c61a2021-08-11 18:05:46 -04001124 var childAdapterEndpoint string
cuilin20187b2a8c32019-03-26 19:52:28 -07001125
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001126 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001127 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001128 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 -07001129 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1130 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001131
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001132 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301133
1134 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1135
Neha Sharma96b7bf22020-06-15 10:37:32 +00001136 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 -07001137 ponPort := plt.IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
cuilin20187b2a8c32019-03-26 19:52:28 -07001138
khenaidoodc2116e2021-10-19 17:33:19 -04001139 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001140 ParentId: dh.device.Id,
1141 OnuId: omciInd.OnuId,
1142 ParentPortNo: ponPort,
1143 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001144 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301145 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001146 "intf-id": omciInd.IntfId,
1147 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001148 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001149 deviceType = onuDevice.Type
1150 deviceID = onuDevice.Id
1151 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
khenaidoo106c61a2021-08-11 18:05:46 -04001152 childAdapterEndpoint = onuDevice.AdapterEndpoint
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001153 //if not exist in cache, then add to cache.
khenaidoo106c61a2021-08-11 18:05:46 -04001154 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false, onuDevice.AdapterEndpoint))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001155 } else {
1156 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001157 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 +05301158 deviceType = onuInCache.(*OnuDevice).deviceType
1159 deviceID = onuInCache.(*OnuDevice).deviceID
1160 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001161 childAdapterEndpoint = onuInCache.(*OnuDevice).adapterEndpoint
cuilin20187b2a8c32019-03-26 19:52:28 -07001162 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001163
khenaidoodc2116e2021-10-19 17:33:19 -04001164 if err := dh.sendOmciIndicationToChildAdapter(ctx, childAdapterEndpoint, &ia.OmciMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001165 ParentDeviceId: proxyDeviceID,
1166 ChildDeviceId: deviceID,
1167 Message: omciInd.Pkt,
1168 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301169 return olterrors.NewErrCommunication("omci-request", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001170 "source": dh.openOLT.config.AdapterEndpoint,
1171 "device-type": deviceType,
1172 "destination": childAdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001174 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001175 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001176 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301177}
1178
khenaidoo106c61a2021-08-11 18:05:46 -04001179// //ProcessInterAdapterMessage sends the proxied messages to the target device
1180// // If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1181// // is meant, and then send the unmarshalled omci message to this onu
khenaidoodc2116e2021-10-19 17:33:19 -04001182// func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ca.InterAdapterMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001183// logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
khenaidoodc2116e2021-10-19 17:33:19 -04001184// if msg.Header.Type == ca.InterAdapterMessageType_OMCI_REQUEST {
khenaidoo106c61a2021-08-11 18:05:46 -04001185// return dh.handleInterAdapterOmciMsg(ctx, msg)
1186// }
1187// return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1188// }
cuilin20187b2a8c32019-03-26 19:52:28 -07001189
kesavandb9f54fd2021-11-25 20:08:04 +05301190// ProxyOmciRequests sends the proxied OMCI message to the target device
1191func (dh *DeviceHandler) ProxyOmciRequests(ctx context.Context, omciMsgs *ia.OmciMessages) error {
1192 if omciMsgs.GetProxyAddress() == nil {
1193 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsgs.ChildDeviceId)
1194 if err != nil {
1195 return olterrors.NewErrNotFound("onu", log.Fields{
1196 "parent-device-id": dh.device.Id,
1197 "child-device-id": omciMsgs.ChildDeviceId}, err)
1198 }
1199 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1200 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsgs); err != nil {
1201 return olterrors.NewErrCommunication("send-failed", log.Fields{
1202 "parent-device-id": dh.device.Id,
1203 "child-device-id": omciMsgs.ChildDeviceId}, err)
1204 }
1205 } else {
1206 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsgs.ProxyAddress})
1207 if err := dh.sendProxyOmciRequests(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsgs); err != nil {
1208 return olterrors.NewErrCommunication("send-failed", log.Fields{
1209 "parent-device-id": dh.device.Id,
1210 "child-device-id": omciMsgs.ChildDeviceId}, err)
1211 }
1212 }
1213 return nil
1214}
1215
1216func (dh *DeviceHandler) sendProxyOmciRequests(ctx context.Context, onuDevice *voltha.Device, omciMsgs *ia.OmciMessages) error {
1217 var intfID uint32
1218 var onuID uint32
1219 var connectStatus common.ConnectStatus_Types
1220 if onuDevice != nil {
1221 intfID = onuDevice.ProxyAddress.GetChannelId()
1222 onuID = onuDevice.ProxyAddress.GetOnuId()
1223 connectStatus = onuDevice.ConnectStatus
1224 } else {
1225 intfID = omciMsgs.GetProxyAddress().GetChannelId()
1226 onuID = omciMsgs.GetProxyAddress().GetOnuId()
1227 connectStatus = omciMsgs.GetConnectStatus()
1228 }
1229 if connectStatus != voltha.ConnectStatus_REACHABLE {
1230 logger.Debugw(ctx, "onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
1231
1232 return olterrors.NewErrCommunication("unreachable", log.Fields{
1233 "intf-id": intfID,
1234 "onu-id": onuID}, nil)
1235 }
1236
1237 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1238 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
1239
1240 onuSecOmciMsgList := omciMsgs.GetMessages()
1241
1242 for _, onuSecOmciMsg := range onuSecOmciMsgList {
1243
1244 var omciMessage *oop.OmciMsg
1245 hexPkt := make([]byte, hex.EncodedLen(len(onuSecOmciMsg)))
1246 hex.Encode(hexPkt, onuSecOmciMsg)
1247 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1248
1249 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1250 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1251 //https://jira.opencord.org/browse/VOL-4604
1252 transid := extractOmciTransactionID(onuSecOmciMsg)
1253 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
1254 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
1255
1256 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
1257 if err != nil {
1258 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
1259 "intf-id": intfID,
1260 "onu-id": onuID,
1261 "message": omciMessage}, err)
1262 }
1263 }
1264 return nil
1265}
1266
khenaidoo106c61a2021-08-11 18:05:46 -04001267// ProxyOmciMessage sends the proxied OMCI message to the target device
khenaidoodc2116e2021-10-19 17:33:19 -04001268func (dh *DeviceHandler) ProxyOmciMessage(ctx context.Context, omciMsg *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04001269 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 -07001270
1271 if omciMsg.GetProxyAddress() == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04001272 onuDevice, err := dh.getDeviceFromCore(ctx, omciMsg.ChildDeviceId)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001273 if err != nil {
1274 return olterrors.NewErrNotFound("onu", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001275 "parent-device-id": dh.device.Id,
1276 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001277 }
khenaidoo106c61a2021-08-11 18:05:46 -04001278 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"onu-device-proxy-address": onuDevice.ProxyAddress})
1279 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), onuDevice, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001280 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001281 "parent-device-id": dh.device.Id,
1282 "child-device-id": omciMsg.ChildDeviceId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001283 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001284 } else {
khenaidoo106c61a2021-08-11 18:05:46 -04001285 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"onu-device-proxy-address": omciMsg.ProxyAddress})
1286 if err := dh.sendProxiedMessage(log.WithSpanFromContext(context.Background(), ctx), nil, omciMsg); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001287 return olterrors.NewErrCommunication("send-failed", log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001288 "parent-device-id": dh.device.Id,
1289 "child-device-id": omciMsg.ChildDeviceId}, err)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001290 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001291 }
1292 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301293}
1294
khenaidoodc2116e2021-10-19 17:33:19 -04001295func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ia.OmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001296 var intfID uint32
1297 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001298 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001299 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001300 intfID = onuDevice.ProxyAddress.GetChannelId()
1301 onuID = onuDevice.ProxyAddress.GetOnuId()
1302 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001303 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001304 intfID = omciMsg.GetProxyAddress().GetChannelId()
1305 onuID = omciMsg.GetProxyAddress().GetOnuId()
1306 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001307 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001308 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001309 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 -08001310
Thomas Lee S94109f12020-03-03 16:39:29 +05301311 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001312 "intf-id": intfID,
1313 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001314 }
1315
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001316 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1317 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
kesavandb9f54fd2021-11-25 20:08:04 +05301318 // https://jira.opencord.org/browse/VOL-4604
lcuie24ef182019-04-29 22:58:36 -07001319 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001320 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1321 hex.Encode(hexPkt, omciMsg.Message)
1322 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1323
1324 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1325 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1326 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001327 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001328 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001329
Neha Sharma8f4e4322020-08-06 10:51:53 +00001330 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001331 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301332 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001333 "intf-id": intfID,
1334 "onu-id": onuID,
1335 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001336 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001337 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001338}
1339
David K. Bainbridge794735f2020-02-11 21:01:37 -08001340func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301341 logger.Debugw(ctx, "activate-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id, "OmccEncryption": dh.openOLT.config.OmccEncryption})
yasin saplibddc2d72022-02-08 13:10:17 +00001342 if err := dh.resourceMgr[intfID].AddNewOnuGemInfoToCacheAndKvStore(ctx, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001343 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001344 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001345 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301346 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301347 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001348 st, _ := status.FromError(err)
1349 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001350 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1351
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001352 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301353 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001354 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001355 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001356 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001357 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001358 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001359}
1360
Mahir Gunyelb0046752021-02-26 13:51:05 -08001361func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362 channelID := onuDiscInd.GetIntfId()
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001363 parentPortNo := plt.IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001364
Mahir Gunyelb0046752021-02-26 13:51:05 -08001365 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001366 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301367
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301368 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001369 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001370 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301371
1372 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1373 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1374 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1375 OnuLosRaise event sent for it */
1376 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1377 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1378 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001379 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301380 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1381 "currentIntfId": onuDiscInd.GetIntfId()})
1382 // TODO:: Should we need to ignore raising OnuLosClear event
1383 // when onu connected to different PON?
1384 }
1385 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1386 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1387 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001388 go func() {
1389 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001390 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001391 }
1392 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301393 }
1394 return true
1395 })
1396
Neha Sharma96b7bf22020-06-15 10:37:32 +00001397 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001398 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001399 }
1400
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001401 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001402
1403 // check the ONU is already know to the OLT
1404 // NOTE the second time the ONU is discovered this should return a device
khenaidoodc2116e2021-10-19 17:33:19 -04001405 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001406 ParentId: dh.device.Id,
1407 SerialNumber: sn,
1408 })
Matteo Scandolo945e4012019-12-12 14:16:11 -08001409
1410 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001411 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 -08001412 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001413 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 -08001414 switch e.Code() {
1415 case codes.Internal:
1416 // this probably means NOT FOUND, so just create a new device
1417 onuDevice = nil
1418 case codes.DeadlineExceeded:
1419 // if the call times out, cleanup and exit
1420 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001421 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001422 }
1423 }
1424 }
1425
1426 if onuDevice == nil {
1427 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001428 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001429 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001430 ponintfid := onuDiscInd.GetIntfId()
yasin saplibddc2d72022-02-08 13:10:17 +00001431 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001432
Neha Sharma96b7bf22020-06-15 10:37:32 +00001433 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001434
1435 if err != nil {
1436 // if we can't create an ID in resource manager,
1437 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001438 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001439 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001440 "pon-intf-id": ponintfid,
1441 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001442 }
1443
khenaidoodc2116e2021-10-19 17:33:19 -04001444 if onuDevice, err = dh.sendChildDeviceDetectedToCore(ctx, &ca.DeviceDiscovery{
khenaidoo106c61a2021-08-11 18:05:46 -04001445 ParentId: dh.device.Id,
1446 ParentPortNo: parentPortNo,
1447 ChannelId: channelID,
1448 VendorId: string(onuDiscInd.SerialNumber.GetVendorId()),
1449 SerialNumber: sn,
1450 OnuId: onuID,
1451 }); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001452 dh.discOnus.Delete(sn)
yasin saplibddc2d72022-02-08 13:10:17 +00001453 dh.resourceMgr[ponintfid].FreeonuID(ctx, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301454 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001455 "pon-intf-id": ponintfid,
1456 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001457 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001458 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 -07001459 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001460 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001461 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301462 log.Fields{"onuDevice": onuDevice,
1463 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001464 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301465 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001466 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001467
khenaidoo106c61a2021-08-11 18:05:46 -04001468 // Setup the gRPC connection to the adapter responsible for that onuDevice, if not setup yet
1469 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
1470 err = dh.setupChildInterAdapterClient(subCtx, onuDevice.AdapterEndpoint)
1471 cancel()
1472 if err != nil {
1473 return olterrors.NewErrCommunication("no-connection-to-child-adapter", log.Fields{"device-id": onuDevice.Id}, err)
1474 }
1475
Matteo Scandolo945e4012019-12-12 14:16:11 -08001476 // we can now use the existing ONU Id
1477 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001478 //Insert the ONU into cache to use in OnuIndication.
1479 //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 +00001480 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001481 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301482 "intfId": onuDiscInd.GetIntfId(),
1483 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001484 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001485
khenaidoo106c61a2021-08-11 18:05:46 -04001486 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301487 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001488 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301489 log.Fields{"onu": onuDev,
1490 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001491
khenaidoodc2116e2021-10-19 17:33:19 -04001492 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001493 DeviceId: onuDevice.Id,
1494 ParentDeviceId: dh.device.Id,
1495 OperStatus: common.OperStatus_DISCOVERED,
1496 ConnStatus: common.ConnectStatus_REACHABLE,
1497 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301498 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001499 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001500 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001501 }
khenaidoo106c61a2021-08-11 18:05:46 -04001502
Neha Sharma96b7bf22020-06-15 10:37:32 +00001503 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001504 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301505 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001506 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001507 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001508 }
1509 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001510}
1511
Mahir Gunyelb0046752021-02-26 13:51:05 -08001512func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001513
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001514 ponPort := plt.IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001515 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001516 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001517 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001518 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301519 log.Fields{"onuId": onuInd.OnuId,
1520 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301521 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001522 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001523 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301524
David K. Bainbridge794735f2020-02-11 21:01:37 -08001525 errFields := log.Fields{"device-id": dh.device.Id}
1526
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301527 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1528
Mahir Gunyele77977b2019-06-27 05:36:22 -07001529 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1530 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001531 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
khenaidoo106c61a2021-08-11 18:05:46 -04001532 onuDevice, err = dh.getDeviceFromCore(ctx, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001533 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001534 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1535 if serialNumber != "" {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001536 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001537 } else {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001538 errFields["onu-id"] = onuInd.OnuId
1539 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001540 }
khenaidoodc2116e2021-10-19 17:33:19 -04001541 onuDevice, err = dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001542 ParentId: dh.device.Id,
1543 SerialNumber: serialNumber,
1544 OnuId: onuInd.OnuId,
1545 ParentPortNo: ponPort,
1546 })
cuilin20187b2a8c32019-03-26 19:52:28 -07001547 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001548
David K. Bainbridge794735f2020-02-11 21:01:37 -08001549 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001550 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001551 }
1552
David K. Bainbridge794735f2020-02-11 21:01:37 -08001553 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001554 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001555 "previousIntfId": onuDevice.ParentPortNo,
1556 "currentIntfId": ponPort})
1557 }
1558
1559 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001560 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301561 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1562 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301563 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001564 }
1565 if !foundInCache {
1566 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1567
khenaidoo106c61a2021-08-11 18:05:46 -04001568 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 -08001569
1570 }
kesavand7cf3a052020-08-28 12:49:18 +05301571 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001572 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001573 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301574 }
1575 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001576 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001577 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001578 }
1579 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001580}
1581
Neha Sharma96b7bf22020-06-15 10:37:32 +00001582func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001583 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 -07001584 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1585 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1586 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1587 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001588 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001589 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1590 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001591 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001592 onuInd.OperState = "down"
1593 }
1594 }
1595
David K. Bainbridge794735f2020-02-11 21:01:37 -08001596 switch onuInd.OperState {
khenaidoo106c61a2021-08-11 18:05:46 -04001597 case "up", "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 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 -04001599
khenaidoodc2116e2021-10-19 17:33:19 -04001600 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001601 DeviceId: onuDevice.Id,
1602 OnuIndication: onuInd,
1603 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001604 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301605 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001606 "onu-indicator": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001607 "source": dh.openOLT.config.AdapterEndpoint,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001608 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001609 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001610 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001611 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001612 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001613 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001614 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001615}
1616
cuilin20187b2a8c32019-03-26 19:52:28 -07001617func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1618 if serialNum != nil {
1619 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001620 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001621 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001622}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001623func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1624 decodedStr, err := hex.DecodeString(serialNum[4:])
1625 if err != nil {
1626 return nil, err
1627 }
1628 return &oop.SerialNumber{
1629 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001630 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001631 }, nil
1632}
cuilin20187b2a8c32019-03-26 19:52:28 -07001633
1634func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001635 if len(vendorSpecific) > 3 {
1636 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1637 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1638 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1639 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1640 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1641 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1642 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1643 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1644 return tmp
1645 }
1646 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001647}
1648
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001649//UpdateFlowsBulk upates the bulk flow
1650func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301651 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001652}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001653
1654//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001655func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1656 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301657 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001658 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301659 "device-id": dh.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001660
khenaidoodc2116e2021-10-19 17:33:19 -04001661 onuDevice, err := dh.getChildDeviceFromCore(ctx, &ca.ChildDeviceFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001662 ParentId: dh.device.Id,
1663 OnuId: onuID,
1664 ParentPortNo: parentPort,
1665 })
1666
Girish Gowdru0c588b22019-04-23 23:24:56 -04001667 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001668 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001669 "intf-id": parentPort,
1670 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001671 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001672 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 -08001673 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301674}
1675
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001676// SendPacketInToCore sends packet-in to core
1677// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1678// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001679func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001680 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001681 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001682 "port": logicalPort,
1683 "packet": hex.EncodeToString(packetPayload),
1684 "device-id": dh.device.Id,
1685 })
1686 }
khenaidoo106c61a2021-08-11 18:05:46 -04001687
khenaidoodc2116e2021-10-19 17:33:19 -04001688 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04001689 DeviceId: dh.device.Id,
1690 Port: logicalPort,
1691 Packet: packetPayload,
1692 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301693 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001694 "source": "adapter",
1695 "destination": "core",
1696 "device-id": dh.device.Id,
1697 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001698 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001699 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001700 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001701 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001702 "packet": hex.EncodeToString(packetPayload),
1703 "device-id": dh.device.Id,
1704 })
1705 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001707}
1708
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001709// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001710func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001711 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001712
1713 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1714 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001715 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001716 }
1717
Kent Hagermane6ff1012020-07-14 15:07:53 -04001718 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001719 metrics := dh.metrics.GetSubscriberMetrics()
1720 for _, m := range pmConfigs.Metrics {
1721 metrics[m.Name].Enabled = m.Enabled
1722
1723 }
1724 }
1725}
1726
khenaidoodc2116e2021-10-19 17:33:19 -04001727func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *of.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001728 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001729 var errorsList []error
1730
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001731 if dh.getDeviceDeletionInProgressFlag() {
1732 // The device itself is going to be reset as part of deletion. So nothing to be done.
1733 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1734 return nil
1735 }
1736
Girish Gowdru0c588b22019-04-23 23:24:56 -04001737 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001738 for _, flow := range flows.ToRemove.Items {
yasin saplid0566272021-12-21 09:10:30 +00001739 intfID := dh.getIntfIDFromFlow(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001740
Neha Sharma96b7bf22020-06-15 10:37:32 +00001741 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301742 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001743 "intfId": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301744 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001745 if flow_utils.HasGroup(flow) {
1746 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1747 } else {
yasin saplid0566272021-12-21 09:10:30 +00001748 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, false, nil)
Girish Gowdra491a9c62021-01-06 16:43:07 -08001749 }
Girish Gowdracefae192020-03-19 18:14:10 -07001750 if err != nil {
Elia Battiston2aaf4342022-02-07 15:16:38 +01001751 if werr, ok := err.(olterrors.WrappedError); ok && status.Code(werr.Unwrap()) == codes.NotFound {
1752 //The flow we want to remove is not there, there is no need to throw an error
1753 logger.Warnw(ctx, "flow-to-remove-not-found",
1754 log.Fields{
1755 "ponIf": intfID,
1756 "flowToRemove": flow,
1757 "error": err,
1758 })
1759 } else {
1760 errorsList = append(errorsList, err)
1761 }
Girish Gowdracefae192020-03-19 18:14:10 -07001762 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001763 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301764
1765 for _, flow := range flows.ToAdd.Items {
yasin saplid0566272021-12-21 09:10:30 +00001766 intfID := dh.getIntfIDFromFlow(ctx, flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001767 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301768 log.Fields{"device-id": device.Id,
yasin saplid0566272021-12-21 09:10:30 +00001769 "ponIf": intfID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301770 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001771 if flow_utils.HasGroup(flow) {
1772 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1773 } else {
yasin saplid0566272021-12-21 09:10:30 +00001774 if dh.flowMgr == nil || dh.flowMgr[intfID] == nil {
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001775 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1776 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1777 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1778 } else {
yasin saplid0566272021-12-21 09:10:30 +00001779 err = dh.flowMgr[intfID].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001780 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001781 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001782 if err != nil {
1783 errorsList = append(errorsList, err)
1784 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301785 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001786 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001787
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001788 return errorsList
1789}
1790
1791func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1792 var err error
1793 var errorsList []error
1794
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08001795 if dh.getDeviceDeletionInProgressFlag() {
1796 // The device itself is going to be reset as part of deletion. So nothing to be done.
1797 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1798 return nil
1799 }
1800
Girish Gowdracefae192020-03-19 18:14:10 -07001801 // 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 +00001802 if groups != nil {
1803 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001804 // err = dh.groupMgr.AddGroup(ctx, group)
1805 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001806 if err != nil {
1807 errorsList = append(errorsList, err)
1808 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001809 }
1810 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001811 // err = dh.groupMgr.ModifyGroup(ctx, group)
1812 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001813 if err != nil {
1814 errorsList = append(errorsList, err)
1815 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001816 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001817 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001818 // err = dh.groupMgr.DeleteGroup(ctx, group)
1819 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001820 if err != nil {
1821 errorsList = append(errorsList, err)
1822 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001823 }
1824 }
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001825
1826 return errorsList
1827}
1828
1829//UpdateFlowsIncrementally updates the device flow
khenaidoodc2116e2021-10-19 17:33:19 -04001830func (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 -07001831
1832 var errorsList []error
Girish Gowdra950326e2021-11-05 12:43:24 -07001833
1834 if dh.getDeviceDeletionInProgressFlag() {
1835 // The device itself is going to be reset as part of deletion. So nothing to be done.
1836 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1837 return nil
1838 }
1839
Girish Gowdra0fb24a32021-10-27 15:15:27 -07001840 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1841 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1842 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001843 if len(errorsList) > 0 {
1844 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1845 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001846 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001847 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301848}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001849
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001850//DisableDevice disables the given device
1851//It marks the following for the given device:
1852//Device-Handler Admin-State : down
1853//Device Port-State: UNKNOWN
1854//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001855func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001856 /* On device disable ,admin state update has to be done prior sending request to agent since
1857 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001858 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001859 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001860 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001861 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001862 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001863 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001864 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001865 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001866 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001867 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301868
1869 dh.discOnus = sync.Map{}
1870 dh.onus = sync.Map{}
1871
Thomas Lee S85f37312020-04-03 17:06:12 +05301872 //stopping the stats collector
1873 dh.stopCollector <- true
1874
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001876 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301877 //Update device Admin state
1878 dh.device = cloned
khenaidoo106c61a2021-08-11 18:05:46 -04001879
kdarapu1afeceb2020-02-12 01:38:09 -05001880 // 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 -04001881 if err := dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001882 DeviceId: cloned.Id,
1883 PortTypeFilter: ^uint32(1 << voltha.Port_PON_OLT),
1884 OperStatus: voltha.OperStatus_UNKNOWN,
1885 }); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001886 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001887 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001888 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001889 return nil
1890}
1891
Neha Sharma96b7bf22020-06-15 10:37:32 +00001892func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001893 // Update onu state as unreachable in onu adapter
1894 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301895 onuInd.OperState = state
khenaidoo106c61a2021-08-11 18:05:46 -04001896
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001897 //get the child device for the parent device
khenaidoo106c61a2021-08-11 18:05:46 -04001898 onuDevices, err := dh.getChildDevicesFromCore(ctx, dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001899 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001900 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 -04001901 }
1902 if onuDevices != nil {
1903 for _, onuDevice := range onuDevices.Items {
khenaidoodc2116e2021-10-19 17:33:19 -04001904 err := dh.sendOnuIndicationToChildAdapter(ctx, onuDevice.AdapterEndpoint, &ia.OnuIndicationMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001905 DeviceId: onuDevice.Id,
1906 OnuIndication: &onuInd,
1907 })
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001908 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001909 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
khenaidoo106c61a2021-08-11 18:05:46 -04001910 "From Adapter": dh.openOLT.config.AdapterEndpoint, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001911 }
1912
1913 }
1914 }
1915
1916}
1917
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001918//ReenableDevice re-enables the olt device after disable
1919//It marks the following for the given device:
1920//Device-Handler Admin-State : up
1921//Device Port-State: ACTIVE
1922//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001923func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001924 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301925 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001926 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301927 }
1928 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001929 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001930
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001931 // Update the all ports state on that device to enable
khenaidoo106c61a2021-08-11 18:05:46 -04001932 ports, err := dh.listDevicePortsFromCore(ctx, device.Id)
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001933 var retError error
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001934 if err != nil {
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001935 retError = olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
1936 } else {
1937 if err := dh.disableAdminDownPorts(ctx, ports.Items); err != nil {
1938 retError = olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
1939 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001940 }
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001941 if retError == nil {
1942 //Update the device oper status as ACTIVE
1943 device.OperStatus = voltha.OperStatus_ACTIVE
1944 } else {
1945 //Update the device oper status as FAILED
1946 device.OperStatus = voltha.OperStatus_FAILED
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001947 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001948 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001949
khenaidoodc2116e2021-10-19 17:33:19 -04001950 if err := dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04001951 DeviceId: device.Id,
1952 OperStatus: device.OperStatus,
1953 ConnStatus: device.ConnectStatus,
1954 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301955 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001956 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001957 "connect-status": device.ConnectStatus,
1958 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001959 }
kesavand39e0aa32020-01-28 20:58:50 -05001960
Neha Sharma96b7bf22020-06-15 10:37:32 +00001961 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001962
Mahir Gunyele5e807a2021-10-22 11:33:25 -07001963 return retError
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001964}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001965
npujarec5762e2020-01-01 14:08:48 +05301966func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001967 var uniID uint32
1968 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301969 for _, port := range onu.UniPorts {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001970 uniID = plt.UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001971 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001972 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001973 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001974 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001975 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001976 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00001977 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001978 for _, tpID := range tpIDList {
yasin saplibddc2d72022-02-08 13:10:17 +00001979 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001980 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001981 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001982 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00001983 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001984 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001985 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001986 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301987 }
yasin saplibddc2d72022-02-08 13:10:17 +00001988 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.OnuID, uniID)
1989 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001990 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301991 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001992 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
yasin saplibddc2d72022-02-08 13:10:17 +00001993 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001994 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 +00001995 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001996 }
1997 return nil
1998}
1999
Devmalya Paul495b94a2019-08-27 19:42:00 -04002000// 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 +05302001func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002002 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04002003 /* Clear the KV store data associated with the all the UNI ports
2004 This clears up flow data and also resource map data for various
2005 other pon resources like alloc_id and gemport_id
2006 */
Girish Gowdra950326e2021-11-05 12:43:24 -07002007
2008 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002009 var wg sync.WaitGroup
2010 wg.Add(1) // for the mcast routine below to finish
2011 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2012 for _, flMgr := range dh.flowMgr {
2013 wg.Add(1) // for the flow handler routine below to finish
2014 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2015 }
2016 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2017 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2018 } else {
2019 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2020 }
Girish Gowdra950326e2021-11-05 12:43:24 -07002021
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002022 dh.cleanupDeviceResources(ctx)
2023 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 -04002024 // Stop the Stats collector
2025 dh.stopCollector <- true
2026 // stop the heartbeat check routine
2027 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05302028 dh.lockDevice.RLock()
2029 // Stop the read indication only if it the routine is active
2030 if dh.isReadIndicationRoutineActive {
2031 dh.stopIndications <- true
2032 }
2033 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002034 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002035 //Reset the state
2036 if dh.Client != nil {
2037 if _, err := dh.Client.Reboot(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).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002039 }
2040 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07002041 // There is no need to update the core about operation status and connection status of the OLT.
2042 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
2043 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
2044 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002045
khenaidoo7eb2d672021-10-22 19:08:50 -04002046 // Stop the adapter grpc clients for that parent device
2047 dh.deleteAdapterClients(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002048 return nil
2049}
Kent Hagermane6ff1012020-07-14 15:07:53 -04002050func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002051
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002052 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302053 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07002054 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002055 var err error
yasin sapli9e4c5092022-02-01 13:52:33 +00002056 onuGemData := dh.resourceMgr[ponPort].GetOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002057 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002058 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03002059 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002060 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302061 }
2062 }
yasin saplibddc2d72022-02-08 13:10:17 +00002063 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx)
2064 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002065 dh.resourceMgr[ponPort].DeleteMcastQueueForIntf(ctx)
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002066 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
2067 logger.Debug(ctx, err)
2068 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04002069 }
yasin saplibddc2d72022-02-08 13:10:17 +00002070 // Clean up NNI manager's data
2071 _ = dh.resourceMgr[dh.totalPonPorts].DeleteAllFlowIDsForGemForIntf(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07002072 }
A R Karthick1f85b802019-10-11 05:06:05 +00002073
Girish Gowdra0f3190e2022-02-11 14:18:28 -08002074 // Take one final sweep at cleaning up KV store for the OLT device
2075 // Clean everything at <base-path-prefix>/openolt/<device-id>
2076 kvClient, err := kvstore.NewEtcdClient(ctx, dh.openOLT.KVStoreAddress, rsrcMgr.KvstoreTimeout, log.FatalLevel)
2077 if err == nil {
2078 kvBackend := &db.Backend{
2079 Client: kvClient,
2080 StoreType: dh.openOLT.KVStoreType,
2081 Address: dh.openOLT.KVStoreAddress,
2082 Timeout: rsrcMgr.KvstoreTimeout,
2083 PathPrefix: fmt.Sprintf(rsrcMgr.BasePathKvStore, dh.cm.Backend.PathPrefix, dh.device.Id)}
2084 _ = kvBackend.DeleteWithPrefix(ctx, "")
2085 }
2086
Devmalya Paul495b94a2019-08-27 19:42:00 -04002087 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05302088 dh.onus.Range(func(key interface{}, value interface{}) bool {
2089 dh.onus.Delete(key)
2090 return true
2091 })
2092
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002093 /*Delete discovered ONU map for the device*/
2094 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
2095 dh.discOnus.Delete(key)
2096 return true
2097 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04002098}
2099
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002100//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002101func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002102 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05302103 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002104 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002105 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04002106 return nil
2107}
2108
David K. Bainbridge794735f2020-02-11 21:01:37 -08002109func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002110 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002111 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002112 "packet-indication": *packetIn,
2113 "device-id": dh.device.Id,
2114 "packet": hex.EncodeToString(packetIn.Pkt),
2115 })
2116 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002117 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002118 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002119 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002120 }
Matteo Scandolo92186242020-06-12 10:54:18 -07002121 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002122 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002123 "logical-port-num": logicalPortNum,
2124 "device-id": dh.device.Id,
2125 "packet": hex.EncodeToString(packetIn.Pkt),
2126 })
2127 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002128
khenaidoodc2116e2021-10-19 17:33:19 -04002129 if err := dh.sendPacketToCore(ctx, &ca.PacketIn{
khenaidoo106c61a2021-08-11 18:05:46 -04002130 DeviceId: dh.device.Id,
2131 Port: logicalPortNum,
2132 Packet: packetIn.Pkt,
2133 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302134 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002135 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05302136 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002137 "device-id": dh.device.Id,
2138 "packet": hex.EncodeToString(packetIn.Pkt),
2139 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002140 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002141
Matteo Scandolo92186242020-06-12 10:54:18 -07002142 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002143 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002144 "packet": hex.EncodeToString(packetIn.Pkt),
2145 "device-id": dh.device.Id,
2146 })
2147 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002148 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002149}
2150
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002151// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
khenaidoo106c61a2021-08-11 18:05:46 -04002152func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo uint32, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07002153 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002154 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002155 "device-id": dh.device.Id,
2156 "egress-port-no": egressPortNo,
2157 "pkt-length": len(packet.Data),
2158 "packet": hex.EncodeToString(packet.Data),
2159 })
2160 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002161
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002162 egressPortType := plt.IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002163 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04002164 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
2165 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302166 if outerEthType == 0x8942 || outerEthType == 0x88cc {
2167 // Do not packet-out lldp packets on uni port.
2168 // ONOS has no clue about uni/nni ports, it just packets out on all
2169 // available ports on the Logical Switch. It should not be interested
2170 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002171 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002172 "device-id": dh.device.Id,
2173 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05302174 return nil
2175 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002176 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
2177 if innerEthType == 0x8100 {
2178 // q-in-q 802.1ad or 802.1q double tagged packet.
2179 // slice out the outer tag.
2180 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07002181 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002182 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002183 "packet-data": hex.EncodeToString(packet.Data),
2184 "device-id": dh.device.Id,
2185 })
2186 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002187 }
2188 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002189 intfID := plt.IntfIDFromUniPortNum(uint32(egressPortNo))
2190 onuID := plt.OnuIDFromPortNum(uint32(egressPortNo))
2191 uniID := plt.UniIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04002192
Girish Gowdra9602eb42020-09-09 15:50:39 -07002193 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002194 if err != nil {
2195 // In this case the openolt agent will receive the gemPortID as 0.
2196 // The agent tries to retrieve the gemPortID in this case.
2197 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002198 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002199 "intf-id": intfID,
2200 "onu-id": onuID,
2201 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002202 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302203 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002204 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04002205 }
2206
2207 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07002208 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002209 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002210 "egress-port-no": egressPortNo,
2211 "intf-id": intfID,
2212 "onu-id": onuID,
2213 "uni-id": uniID,
2214 "gem-port-id": gemPortID,
2215 "packet": hex.EncodeToString(packet.Data),
2216 "device-id": dh.device.Id,
2217 })
2218 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002219
npujarec5762e2020-01-01 14:08:48 +05302220 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302221 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002222 "source": "adapter",
2223 "destination": "onu",
2224 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07002225 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08002226 "oni-id": onuID,
2227 "uni-id": uniID,
2228 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002229 "packet": hex.EncodeToString(packet.Data),
2230 "device-id": dh.device.Id,
2231 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002232 }
2233 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002234 nniIntfID, err := plt.IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002235 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002236 return olterrors.NewErrInvalidValue(log.Fields{
2237 "egress-nni-port": egressPortNo,
2238 "device-id": dh.device.Id,
2239 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002240 }
2241 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002242
Matteo Scandolo92186242020-06-12 10:54:18 -07002243 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002244 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002245 "uplink-pkt": uplinkPkt,
2246 "packet": hex.EncodeToString(packet.Data),
2247 "device-id": dh.device.Id,
2248 })
2249 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002250
npujarec5762e2020-01-01 14:08:48 +05302251 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002252 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2253 "packet": hex.EncodeToString(packet.Data),
2254 "device-id": dh.device.Id,
2255 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002256 }
2257 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002258 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302259 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002260 "egressPortType": egressPortType,
2261 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302262 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002263 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002264 }
2265 return nil
2266}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002267
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002268func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2269 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002270}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302271
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002272func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002273
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302274 // start the heartbeat check towards the OLT.
2275 var timerCheck *time.Timer
2276
2277 for {
2278 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2279 select {
2280 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002281 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002282 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002283 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302284 if timerCheck == nil {
2285 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002286 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302287 }
2288 } else {
2289 if timerCheck != nil {
2290 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002291 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302292 }
2293 timerCheck = nil
2294 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002295 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302296 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302297 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302298 }
2299 cancel()
2300 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002301 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302302 return
2303 }
2304 }
2305}
2306
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002307func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
khenaidoo106c61a2021-08-11 18:05:46 -04002308 device, err := dh.getDeviceFromCore(ctx, dh.device.Id)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002309 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002310 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2311 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2312 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2313 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2314 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002315 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002316 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2317 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002318 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302319
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002320 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2321 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002322 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
khenaidoodc2116e2021-10-19 17:33:19 -04002323 if err = dh.updateDeviceStateInCore(ctx, &ca.DeviceStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002324 DeviceId: dh.device.Id,
2325 OperStatus: voltha.OperStatus_UNKNOWN,
2326 ConnStatus: voltha.ConnectStatus_UNREACHABLE,
2327 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002328 _ = 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 -04002329 }
khenaidoo106c61a2021-08-11 18:05:46 -04002330
khenaidoodc2116e2021-10-19 17:33:19 -04002331 if err = dh.updatePortsStateInCore(ctx, &ca.PortStateFilter{
khenaidoo106c61a2021-08-11 18:05:46 -04002332 DeviceId: dh.device.Id,
2333 PortTypeFilter: 0,
2334 OperStatus: voltha.OperStatus_UNKNOWN,
2335 }); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002336 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002337 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002338
2339 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002340 raisedTs := time.Now().Unix()
khenaidoo106c61a2021-08-11 18:05:46 -04002341 cloned := proto.Clone(device).(*voltha.Device)
2342 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2343 cloned.OperStatus = voltha.OperStatus_UNKNOWN
2344 dh.device = cloned // update local copy of the device
2345 go dh.eventMgr.oltCommunicationEvent(ctx, cloned, raisedTs)
Gamze Abaka07868a52020-12-17 14:19:28 +00002346
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002347 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002348 // Stop the Stats collector
2349 dh.stopCollector <- true
2350 // stop the heartbeat check routine
2351 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002352
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002353 dh.lockDevice.RLock()
2354 // Stop the read indication only if it the routine is active
2355 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2356 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2357 // on next execution of the readIndication routine.
2358 if dh.isReadIndicationRoutineActive {
2359 dh.stopIndications <- true
2360 }
2361 dh.lockDevice.RUnlock()
2362
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002363 var wg sync.WaitGroup
2364 wg.Add(1) // for the multicast handler routine
2365 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002366 for _, flMgr := range dh.flowMgr {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002367 wg.Add(1) // for the flow handler routine
2368 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2369 }
2370 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2371 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2372 } else {
2373 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002374 }
2375
Gamze Abakac2c32a62021-03-11 11:44:18 +00002376 //reset adapter reconcile flag
2377 dh.adapterPreviouslyConnected = false
2378
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002379 dh.transitionMap.Handle(ctx, DeviceInit)
2380
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302381 }
2382}
kesavand39e0aa32020-01-28 20:58:50 -05002383
2384// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002385func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2386 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2387 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002388}
2389
2390// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2392 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2393 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002394}
2395
kdarapu1afeceb2020-02-12 01:38:09 -05002396//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 +00002397func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2398 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002399 if port.GetType() == voltha.Port_ETHERNET_NNI {
2400 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002401 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302402 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302403 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002404 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002405 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002406 }
2407 // fetch interfaceid from PortNo
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002408 ponID := plt.PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
kesavand39e0aa32020-01-28 20:58:50 -05002409 ponIntf := &oop.Interface{IntfId: ponID}
2410 var operStatus voltha.OperStatus_Types
2411 if enablePort {
2412 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302413 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002414
2415 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302416 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002417 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002418 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002419 }
2420 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002421 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002422 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002423 } else {
2424 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302425 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002426 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302427 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002428 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002429 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002430 }
2431 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002432 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002433 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002434 }
khenaidoodc2116e2021-10-19 17:33:19 -04002435 if err := dh.updatePortStateInCore(ctx, &ca.PortState{
khenaidoo106c61a2021-08-11 18:05:46 -04002436 DeviceId: dh.device.Id,
2437 PortType: voltha.Port_PON_OLT,
2438 PortNo: port.PortNo,
2439 OperStatus: operStatus,
2440 }); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302441 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302442 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002443 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002444 }
2445 return nil
2446}
2447
kdarapu1afeceb2020-02-12 01:38:09 -05002448//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002449func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002450 // Disable the port and update the oper_port_status to core
2451 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002452 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002453 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002454 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302455 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302456 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002457 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002458 }
2459 }
2460 }
2461 return nil
2462}
2463
2464//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002465func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2466 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2467 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002468 if port.Type == voltha.Port_ETHERNET_NNI {
2469 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002470 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002471 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002472 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002473 }
2474 }
2475 if port.Type == voltha.Port_PON_OLT {
2476 if port.OperStatus == voltha.OperStatus_ACTIVE {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002477 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002478 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002479 dh.activePorts.Store(plt.PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002480 }
2481 }
2482 }
2483}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002484
2485// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002486func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002487 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002488 intfID := plt.PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002489 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002490
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002491 var sn *oop.SerialNumber
2492 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002493 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302494 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002495 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302496 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002497 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002498 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002499
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002500 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002501 //clear PON resources associated with ONU
yasin saplibddc2d72022-02-08 13:10:17 +00002502 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, onuID)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002503 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2504 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2505 "device-id": dh.device.Id,
2506 "intf-id": intfID,
2507 "onuID": onuID,
2508 "err": err})
2509 } else {
2510 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
2511 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2512 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2513 "device-id": dh.device.Id,
2514 "onu-device": onu,
2515 "err": err})
2516 }
2517 // Clear flowids for gem cache.
2518 for _, gem := range onuGem.GemPorts {
yasin saplibddc2d72022-02-08 13:10:17 +00002519 _ = dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, gem)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002520 }
yasin saplibddc2d72022-02-08 13:10:17 +00002521 if err := dh.resourceMgr[intfID].DelOnuGemInfo(ctx, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002522 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2523 "intf-id": intfID,
2524 "onu-device": onu,
2525 "onu-gem": onuGem,
2526 "err": err})
2527 //Not returning error on cleanup.
2528 }
2529 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
Himani Chawlabcc95852021-10-27 10:55:40 +05302530
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002531 }
yasin saplibddc2d72022-02-08 13:10:17 +00002532 dh.resourceMgr[intfID].FreeonuID(ctx, []uint32{onuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002533 dh.onus.Delete(onuKey)
2534 dh.discOnus.Delete(onuSn)
2535
2536 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002537 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302538 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302539 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002540 "onu-id": onuID}, err).Log()
2541 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002542
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002543 return nil
2544}
Girish Gowdracefae192020-03-19 18:14:10 -07002545
2546func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002547 for _, field := range flow_utils.GetOfbFields(flow) {
2548 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002549 return field.GetPort()
2550 }
2551 }
2552 return InvalidPort
2553}
2554
2555func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002556 for _, action := range flow_utils.GetActions(flow) {
2557 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002558 if out := action.GetOutput(); out != nil {
2559 return out.GetPort()
2560 }
2561 }
2562 }
2563 return InvalidPort
2564}
2565
Girish Gowdracefae192020-03-19 18:14:10 -07002566func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2567 inPort := getInPortFromFlow(flow)
2568 outPort := getOutPortFromFlow(flow)
2569
2570 if inPort == InvalidPort || outPort == InvalidPort {
2571 return inPort, outPort
2572 }
2573
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002574 if isControllerFlow := plt.IsControllerBoundFlow(outPort); isControllerFlow {
Girish Gowdracefae192020-03-19 18:14:10 -07002575 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002576 if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002577 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002578 return uniPort, outPort
2579 }
2580 }
2581 } else {
2582 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002583 if portType := plt.IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002584 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002585 return inPort, uniPort
2586 }
2587 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002588 } else if portType := plt.IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002589 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002590 return uniPort, outPort
2591 }
2592 }
2593 }
2594
2595 return InvalidPort, InvalidPort
2596}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002597
2598func extractOmciTransactionID(omciPkt []byte) uint16 {
2599 if len(omciPkt) > 3 {
2600 d := omciPkt[0:2]
2601 transid := binary.BigEndian.Uint16(d)
2602 return transid
2603 }
2604 return 0
2605}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002606
2607// StoreOnuDevice stores the onu parameters to the local cache.
2608func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2609 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2610 dh.onus.Store(onuKey, onuDevice)
2611}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002612
khenaidoodc2116e2021-10-19 17:33:19 -04002613func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value extension.ValueType_Type) (*extension.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002614 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002615 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002616 var ID uint32
khenaidoodc2116e2021-10-19 17:33:19 -04002617 resp := new(extension.ReturnValues)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002618 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002619 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002620 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002621 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2622 return nil, err
2623 }
2624 ID = device.ProxyAddress.GetOnuId()
2625 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2626 valueparam.Onu = &Onu
2627 valueparam.Value = value
2628
2629 // This API is unsupported until agent patch is added
2630 resp.Unsupported = uint32(value)
2631 _ = ctx
2632
2633 // Uncomment this code once agent changes are complete and tests
2634 /*
2635 resp, err = dh.Client.GetValue(ctx, valueparam)
2636 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002637 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002638 return nil, err
2639 }
2640 */
2641
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002642 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 -08002643 return resp, nil
2644}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002645
yasin saplid0566272021-12-21 09:10:30 +00002646func (dh *DeviceHandler) getIntfIDFromFlow(ctx context.Context, flow *of.OfpFlowStats) uint32 {
2647 // Default to NNI
2648 var intfID = dh.totalPonPorts
Girish Gowdra9602eb42020-09-09 15:50:39 -07002649 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002650 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002651 _, intfID, _, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002652 }
2653 return intfID
2654}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002655
Mahir Gunyelb0046752021-02-26 13:51:05 -08002656func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2657 dh.perPonOnuIndicationChannelLock.Lock()
2658 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2659 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002660 return ch.indicationChannel
2661 }
2662 channels := onuIndicationChannels{
2663 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002664 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002665 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002666 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002667 stopChannel: make(chan struct{}),
2668 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002669 dh.perPonOnuIndicationChannel[intfID] = channels
2670 dh.perPonOnuIndicationChannelLock.Unlock()
2671 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002672 return channels.indicationChannel
2673
2674}
2675
Mahir Gunyelb0046752021-02-26 13:51:05 -08002676func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2677 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2678 dh.perPonOnuIndicationChannelLock.Lock()
2679 defer dh.perPonOnuIndicationChannelLock.Unlock()
2680 for _, v := range dh.perPonOnuIndicationChannel {
2681 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002682 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002683 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002684}
2685
Mahir Gunyelb0046752021-02-26 13:51:05 -08002686func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2687 ind := onuIndicationMsg{
2688 ctx: ctx,
2689 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002690 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002691 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002692 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002693 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002694}
2695
Mahir Gunyelb0046752021-02-26 13:51:05 -08002696func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002697 for {
2698 select {
2699 // process one indication per onu, before proceeding to the next one
2700 case onuInd := <-onuChannels.indicationChannel:
Andrea Campanella46b01402021-11-15 16:58:05 -08002701 indication := *(proto.Clone(onuInd.indication)).(*oop.Indication)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002702 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Andrea Campanella46b01402021-11-15 16:58:05 -08002703 "ind": indication})
2704 switch indication.Data.(type) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002705 case *oop.Indication_OnuInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002706 if err := dh.onuIndication(onuInd.ctx, indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002707 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2708 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002709 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002710 }
2711 case *oop.Indication_OnuDiscInd:
Andrea Campanella46b01402021-11-15 16:58:05 -08002712 if err := dh.onuDiscIndication(onuInd.ctx, indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002713 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2714 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002715 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002716 }
2717 }
2718 case <-onuChannels.stopChannel:
2719 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2720 close(onuChannels.indicationChannel)
2721 return
2722 }
2723 }
2724}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002725
2726// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2727// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
khenaidoodc2116e2021-10-19 17:33:19 -04002728func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *of.OfpFlowStats, group *of.OfpGroupEntry, action string) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002729 if dh.getDeviceDeletionInProgressFlag() {
2730 // The device itself is going to be reset as part of deletion. So nothing to be done.
2731 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2732 return nil
2733 }
2734
Girish Gowdra491a9c62021-01-06 16:43:07 -08002735 // Step1 : Fill McastFlowOrGroupControlBlock
2736 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2737 // Step3 : Wait on response channel for response
2738 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002739 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002740 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2741 errChan := make(chan error)
2742 var groupID uint32
2743 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2744 ctx: ctx,
2745 flowOrGroupAction: action,
2746 flow: flow,
2747 group: group,
2748 errChan: &errChan,
2749 }
2750 if flow != nil {
2751 groupID = flow_utils.GetGroup(flow)
2752 } else if group != nil {
2753 groupID = group.Desc.GroupId
2754 } else {
2755 return errors.New("flow-and-group-both-nil")
2756 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002757 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2758 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2759 // Derive the appropriate go routine to handle the request by a simple module operation.
2760 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2761 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2762 // Wait for handler to return error value
2763 err := <-errChan
2764 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2765 return err
2766 }
2767 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2768 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002769}
2770
2771// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002772func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002773 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002774 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002775 // block on the channel to receive an incoming mcast flow/group
2776 // process the flow completely before proceeding to handle the next flow
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002777 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2778 if mcastFlowOrGroupCb.flow != nil {
2779 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2780 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2781 log.Fields{"device-id": dh.device.Id,
2782 "flowToAdd": mcastFlowOrGroupCb.flow})
2783 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2784 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2785 // Pass the return value over the return channel
2786 *mcastFlowOrGroupCb.errChan <- err
2787 } else { // flow remove
2788 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2789 log.Fields{"device-id": dh.device.Id,
2790 "flowToRemove": mcastFlowOrGroupCb.flow})
2791 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2792 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2793 // Pass the return value over the return channel
2794 *mcastFlowOrGroupCb.errChan <- err
2795 }
2796 } else { // mcast group
2797 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2798 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2799 log.Fields{"device-id": dh.device.Id,
2800 "groupToAdd": mcastFlowOrGroupCb.group})
2801 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2802 // Pass the return value over the return channel
2803 *mcastFlowOrGroupCb.errChan <- err
2804 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2805 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2806 log.Fields{"device-id": dh.device.Id,
2807 "groupToModify": mcastFlowOrGroupCb.group})
2808 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2809 // Pass the return value over the return channel
2810 *mcastFlowOrGroupCb.errChan <- err
2811 } else { // group remove
2812 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2813 log.Fields{"device-id": dh.device.Id,
2814 "groupToRemove": mcastFlowOrGroupCb.group})
2815 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2816 // Pass the return value over the return channel
2817 *mcastFlowOrGroupCb.errChan <- err
2818 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002819 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002820 case <-stopHandler:
2821 dh.mcastHandlerRoutineActive[routineIndex] = false
2822 return
Girish Gowdra491a9c62021-01-06 16:43:07 -08002823 }
2824 }
2825}
kesavand62126212021-01-12 04:56:06 -05002826
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002827// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002828func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002829 for i, v := range dh.stopMcastHandlerRoutine {
2830 if dh.mcastHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002831 select {
2832 case v <- true:
2833 case <-time.After(time.Second * 5):
2834 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
2835 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002836 }
2837 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002838 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002839 logger.Debug(ctx, "stopped all mcast handler routines")
2840}
2841
kesavand62126212021-01-12 04:56:06 -05002842func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2843
2844 singleValResp := extension.SingleGetValueResponse{
2845 Response: &extension.GetValueResponse{
2846 Response: &extension.GetValueResponse_PortCoutners{
2847 PortCoutners: &extension.GetOltPortCountersResponse{},
2848 },
2849 },
2850 }
2851
2852 errResp := func(status extension.GetValueResponse_Status,
2853 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2854 return &extension.SingleGetValueResponse{
2855 Response: &extension.GetValueResponse{
2856 Status: status,
2857 ErrReason: reason,
2858 },
2859 }
2860 }
2861
2862 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2863 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2864 //send error response
2865 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2866 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2867 }
2868 statIndChn := make(chan bool, 1)
2869 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2870 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2871 //request openOlt agent to send the the port statistics indication
2872
2873 go func() {
2874 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2875 if err != nil {
2876 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2877 }
2878 }()
2879 select {
2880 case <-statIndChn:
2881 //indication received for ports stats
2882 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2883 case <-time.After(oltPortInfoTimeout * time.Second):
2884 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2885 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2886 case <-ctx.Done():
2887 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2888 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2889 }
2890 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2891 //get nni stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002892 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
kesavand62126212021-01-12 04:56:06 -05002893 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2894 cmnni := dh.portStats.collectNNIMetrics(intfID)
2895 if cmnni == nil {
2896 //TODO define the error reason
2897 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2898 }
2899 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2900 return &singleValResp
2901
2902 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2903 // get pon stats
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002904 intfID := plt.PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
kesavand62126212021-01-12 04:56:06 -05002905 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2906 cmpon := dh.portStats.collectPONMetrics(intfID)
2907 if cmpon == nil {
2908 //TODO define the error reason
2909 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2910 }
2911 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2912 return &singleValResp
2913 }
2914 }
2915 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2916}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302917
2918func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2919
2920 singleValResp := extension.SingleGetValueResponse{
2921 Response: &extension.GetValueResponse{
2922 Response: &extension.GetValueResponse_OnuPonCounters{
2923 OnuPonCounters: &extension.GetOnuCountersResponse{},
2924 },
2925 },
2926 }
2927
2928 errResp := func(status extension.GetValueResponse_Status,
2929 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2930 return &extension.SingleGetValueResponse{
2931 Response: &extension.GetValueResponse{
2932 Status: status,
2933 ErrReason: reason,
2934 },
2935 }
2936 }
2937 intfID := onuPonInfo.IntfId
2938 onuID := onuPonInfo.OnuId
2939 onuKey := dh.formOnuKey(intfID, onuID)
2940
2941 if _, ok := dh.onus.Load(onuKey); !ok {
2942 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2943 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2944 }
2945 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2946 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2947 if cmnni == nil {
2948 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2949 }
2950 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2951 return &singleValResp
2952
2953}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002954
2955func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2956
2957 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
2958 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
2959 if err != nil {
2960 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
2961 return generateSingleGetValueErrorResponse(err)
2962 }
2963 return &extension.SingleGetValueResponse{
2964 Response: &extension.GetValueResponse{
2965 Status: extension.GetValueResponse_OK,
2966 Response: &extension.GetValueResponse_RxPower{
2967 RxPower: &extension.GetRxPowerResponse{
2968 IntfId: rxPowerRequest.IntfId,
2969 OnuId: rxPowerRequest.OnuId,
2970 Status: rxPower.Status,
2971 FailReason: rxPower.FailReason.String(),
2972 RxPower: rxPower.RxPowerMeanDbm,
2973 },
2974 },
2975 },
2976 }
2977}
2978
2979func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
2980 errResp := func(status extension.GetValueResponse_Status,
2981 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2982 return &extension.SingleGetValueResponse{
2983 Response: &extension.GetValueResponse{
2984 Status: status,
2985 ErrReason: reason,
2986 },
2987 }
2988 }
2989
2990 if err != nil {
2991 if e, ok := status.FromError(err); ok {
2992 switch e.Code() {
2993 case codes.Internal:
2994 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2995 case codes.DeadlineExceeded:
2996 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2997 case codes.Unimplemented:
2998 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
2999 case codes.NotFound:
3000 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
3001 }
3002 }
3003 }
3004
3005 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
3006}
khenaidoo106c61a2021-08-11 18:05:46 -04003007
3008/*
3009Helper functions to communicate with Core
3010*/
3011
3012func (dh *DeviceHandler) getDeviceFromCore(ctx context.Context, deviceID string) (*voltha.Device, error) {
3013 cClient, err := dh.coreClient.GetCoreServiceClient()
3014 if err != nil || cClient == nil {
3015 return nil, err
3016 }
3017 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3018 defer cancel()
3019 return cClient.GetDevice(subCtx, &common.ID{Id: deviceID})
3020}
3021
khenaidoodc2116e2021-10-19 17:33:19 -04003022func (dh *DeviceHandler) getChildDeviceFromCore(ctx context.Context, childDeviceFilter *ca.ChildDeviceFilter) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003023 cClient, err := dh.coreClient.GetCoreServiceClient()
3024 if err != nil || cClient == nil {
3025 return nil, err
3026 }
3027 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3028 defer cancel()
3029 return cClient.GetChildDevice(subCtx, childDeviceFilter)
3030}
3031
khenaidoodc2116e2021-10-19 17:33:19 -04003032func (dh *DeviceHandler) updateDeviceStateInCore(ctx context.Context, deviceStateFilter *ca.DeviceStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003033 cClient, err := dh.coreClient.GetCoreServiceClient()
3034 if err != nil || cClient == nil {
3035 return err
3036 }
3037 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3038 defer cancel()
3039 _, err = cClient.DeviceStateUpdate(subCtx, deviceStateFilter)
3040 return err
3041}
3042
3043func (dh *DeviceHandler) getChildDevicesFromCore(ctx context.Context, deviceID string) (*voltha.Devices, error) {
3044 cClient, err := dh.coreClient.GetCoreServiceClient()
3045 if err != nil || cClient == nil {
3046 return nil, err
3047 }
3048 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3049 defer cancel()
3050 return cClient.GetChildDevices(subCtx, &common.ID{Id: deviceID})
3051}
3052
3053func (dh *DeviceHandler) listDevicePortsFromCore(ctx context.Context, deviceID string) (*voltha.Ports, error) {
3054 cClient, err := dh.coreClient.GetCoreServiceClient()
3055 if err != nil || cClient == nil {
3056 return nil, err
3057 }
3058 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3059 defer cancel()
3060 return cClient.ListDevicePorts(subCtx, &common.ID{Id: deviceID})
3061}
3062
3063func (dh *DeviceHandler) updateDeviceInCore(ctx context.Context, device *voltha.Device) error {
3064 cClient, err := dh.coreClient.GetCoreServiceClient()
3065 if err != nil || cClient == nil {
3066 return err
3067 }
3068 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3069 defer cancel()
3070 _, err = cClient.DeviceUpdate(subCtx, device)
3071 return err
3072}
3073
khenaidoodc2116e2021-10-19 17:33:19 -04003074func (dh *DeviceHandler) sendChildDeviceDetectedToCore(ctx context.Context, deviceDiscoveryInfo *ca.DeviceDiscovery) (*voltha.Device, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003075 cClient, err := dh.coreClient.GetCoreServiceClient()
3076 if err != nil || cClient == nil {
3077 return nil, err
3078 }
3079 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3080 defer cancel()
3081 return cClient.ChildDeviceDetected(subCtx, deviceDiscoveryInfo)
3082}
3083
khenaidoodc2116e2021-10-19 17:33:19 -04003084func (dh *DeviceHandler) sendPacketToCore(ctx context.Context, pkt *ca.PacketIn) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003085 cClient, err := dh.coreClient.GetCoreServiceClient()
3086 if err != nil || cClient == nil {
3087 return err
3088 }
3089 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3090 defer cancel()
3091 _, err = cClient.SendPacketIn(subCtx, pkt)
3092 return err
3093}
3094
3095func (dh *DeviceHandler) createPortInCore(ctx context.Context, port *voltha.Port) error {
3096 cClient, err := dh.coreClient.GetCoreServiceClient()
3097 if err != nil || cClient == nil {
3098 return err
3099 }
3100 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3101 defer cancel()
3102 _, err = cClient.PortCreated(subCtx, port)
3103 return err
3104}
3105
khenaidoodc2116e2021-10-19 17:33:19 -04003106func (dh *DeviceHandler) updatePortsStateInCore(ctx context.Context, portFilter *ca.PortStateFilter) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003107 cClient, err := dh.coreClient.GetCoreServiceClient()
3108 if err != nil || cClient == nil {
3109 return err
3110 }
3111 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3112 defer cancel()
3113 _, err = cClient.PortsStateUpdate(subCtx, portFilter)
3114 return err
3115}
3116
khenaidoodc2116e2021-10-19 17:33:19 -04003117func (dh *DeviceHandler) updatePortStateInCore(ctx context.Context, portState *ca.PortState) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003118 cClient, err := dh.coreClient.GetCoreServiceClient()
3119 if err != nil || cClient == nil {
3120 return err
3121 }
3122 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3123 defer cancel()
3124 _, err = cClient.PortStateUpdate(subCtx, portState)
3125 return err
3126}
3127
khenaidoodc2116e2021-10-19 17:33:19 -04003128func (dh *DeviceHandler) getPortFromCore(ctx context.Context, portFilter *ca.PortFilter) (*voltha.Port, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003129 cClient, err := dh.coreClient.GetCoreServiceClient()
3130 if err != nil || cClient == nil {
3131 return nil, err
3132 }
3133 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3134 defer cancel()
3135 return cClient.GetDevicePort(subCtx, portFilter)
3136}
3137
3138/*
3139Helper functions to communicate with child adapter
3140*/
3141
khenaidoodc2116e2021-10-19 17:33:19 -04003142func (dh *DeviceHandler) sendOmciIndicationToChildAdapter(ctx context.Context, childEndpoint string, response *ia.OmciMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003143 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3144 if err != nil || aClient == nil {
3145 return err
3146 }
3147 logger.Debugw(ctx, "sending-omci-response", log.Fields{"response": response, "child-endpoint": childEndpoint})
3148 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3149 defer cancel()
3150 _, err = aClient.OmciIndication(subCtx, response)
3151 return err
3152}
3153
khenaidoodc2116e2021-10-19 17:33:19 -04003154func (dh *DeviceHandler) sendOnuIndicationToChildAdapter(ctx context.Context, childEndpoint string, onuInd *ia.OnuIndicationMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003155 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3156 if err != nil || aClient == nil {
3157 return err
3158 }
3159 logger.Debugw(ctx, "sending-onu-indication", log.Fields{"onu-indication": onuInd, "child-endpoint": childEndpoint})
3160 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3161 defer cancel()
3162 _, err = aClient.OnuIndication(subCtx, onuInd)
3163 return err
3164}
3165
khenaidoodc2116e2021-10-19 17:33:19 -04003166func (dh *DeviceHandler) sendDeleteTContToChildAdapter(ctx context.Context, childEndpoint string, tContInfo *ia.DeleteTcontMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003167 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3168 if err != nil || aClient == nil {
3169 return err
3170 }
3171 logger.Debugw(ctx, "sending-delete-tcont", log.Fields{"tcont": tContInfo, "child-endpoint": childEndpoint})
3172 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3173 defer cancel()
3174 _, err = aClient.DeleteTCont(subCtx, tContInfo)
3175 return err
3176}
3177
khenaidoodc2116e2021-10-19 17:33:19 -04003178func (dh *DeviceHandler) sendDeleteGemPortToChildAdapter(ctx context.Context, childEndpoint string, gemPortInfo *ia.DeleteGemPortMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003179 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3180 if err != nil || aClient == nil {
3181 return err
3182 }
3183 logger.Debugw(ctx, "sending-delete-gem-port", log.Fields{"gem-port-info": gemPortInfo, "child-endpoint": childEndpoint})
3184 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3185 defer cancel()
3186 _, err = aClient.DeleteGemPort(subCtx, gemPortInfo)
3187 return err
3188}
3189
khenaidoodc2116e2021-10-19 17:33:19 -04003190func (dh *DeviceHandler) sendDownloadTechProfileToChildAdapter(ctx context.Context, childEndpoint string, tpDownloadInfo *ia.TechProfileDownloadMessage) error {
khenaidoo106c61a2021-08-11 18:05:46 -04003191 aClient, err := dh.getChildAdapterServiceClient(childEndpoint)
3192 if err != nil || aClient == nil {
3193 return err
3194 }
3195 logger.Debugw(ctx, "sending-tech-profile-download", log.Fields{"tp-download-info": tpDownloadInfo, "child-endpoint": childEndpoint})
3196 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.cfg.RPCTimeout)
3197 defer cancel()
3198 _, err = aClient.DownloadTechProfile(subCtx, tpDownloadInfo)
3199 return err
3200}
3201
3202/*
3203Helper functions for remote communication
3204*/
3205
3206// TODO: Use a connection tracker such that the adapter connection is stopped when the last device that adapter
3207// supports is deleted
3208func (dh *DeviceHandler) setupChildInterAdapterClient(ctx context.Context, endpoint string) error {
3209 logger.Infow(ctx, "setting-child-adapter-connection", log.Fields{"child-endpoint": endpoint})
3210
3211 dh.lockChildAdapterClients.Lock()
3212 defer dh.lockChildAdapterClients.Unlock()
3213 if _, ok := dh.childAdapterClients[endpoint]; ok {
3214 // Already set
3215 return nil
3216 }
3217
3218 // Setup child's adapter grpc connection
3219 var err error
khenaidoo27e7ac92021-12-08 14:43:09 -05003220 if dh.childAdapterClients[endpoint], err = vgrpc.NewClient(
3221 dh.cfg.AdapterEndpoint,
3222 endpoint,
khenaidooefff76e2021-12-15 16:51:30 -05003223 "onu_inter_adapter_service.OnuInterAdapterService",
3224 dh.onuInterAdapterRestarted,
3225 vgrpc.ClientContextData(dh.device.Id)); err != nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003226 logger.Errorw(ctx, "grpc-client-not-created", log.Fields{"error": err, "endpoint": endpoint})
3227 return err
3228 }
khenaidooefff76e2021-12-15 16:51:30 -05003229 go dh.childAdapterClients[endpoint].Start(log.WithSpanFromContext(context.TODO(), ctx), dh.getOnuInterAdapterServiceClientHandler)
khenaidoo106c61a2021-08-11 18:05:46 -04003230
3231 // Wait until we have a connection to the child adapter.
3232 // Unlimited retries or until context expires
3233 subCtx := log.WithSpanFromContext(context.TODO(), ctx)
3234 backoff := vgrpc.NewBackoff(dh.cfg.MinBackoffRetryDelay, dh.cfg.MaxBackoffRetryDelay, 0)
3235 for {
3236 client, err := dh.childAdapterClients[endpoint].GetOnuInterAdapterServiceClient()
3237 if err == nil && client != nil {
3238 logger.Infow(subCtx, "connected-to-child-adapter", log.Fields{"child-endpoint": endpoint})
3239 break
3240 }
3241 logger.Warnw(subCtx, "connection-to-child-adapter-not-ready", log.Fields{"error": err, "child-endpoint": endpoint})
3242 // Backoff
3243 if err = backoff.Backoff(subCtx); err != nil {
3244 logger.Errorw(subCtx, "received-error-on-backoff", log.Fields{"error": err, "child-endpoint": endpoint})
3245 break
3246 }
3247 }
3248 return nil
3249}
3250
khenaidoodc2116e2021-10-19 17:33:19 -04003251func (dh *DeviceHandler) getChildAdapterServiceClient(endpoint string) (onu_inter_adapter_service.OnuInterAdapterServiceClient, error) {
khenaidoo106c61a2021-08-11 18:05:46 -04003252
3253 // First check from cache
3254 dh.lockChildAdapterClients.RLock()
3255 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3256 dh.lockChildAdapterClients.RUnlock()
3257 return cgClient.GetOnuInterAdapterServiceClient()
3258 }
3259 dh.lockChildAdapterClients.RUnlock()
3260
3261 // Set the child connection - can occur on restarts
3262 ctx, cancel := context.WithTimeout(context.Background(), dh.cfg.RPCTimeout)
3263 err := dh.setupChildInterAdapterClient(ctx, endpoint)
3264 cancel()
3265 if err != nil {
3266 return nil, err
3267 }
3268
3269 // Get the child client now
3270 dh.lockChildAdapterClients.RLock()
3271 defer dh.lockChildAdapterClients.RUnlock()
3272 if cgClient, ok := dh.childAdapterClients[endpoint]; ok {
3273 return cgClient.GetOnuInterAdapterServiceClient()
3274 }
3275 return nil, fmt.Errorf("no-client-for-endpoint-%s", endpoint)
3276}
3277
3278func (dh *DeviceHandler) deleteAdapterClients(ctx context.Context) {
3279 dh.lockChildAdapterClients.Lock()
3280 defer dh.lockChildAdapterClients.Unlock()
3281 for key, client := range dh.childAdapterClients {
3282 client.Stop(ctx)
3283 delete(dh.childAdapterClients, key)
3284 }
3285}
3286
khenaidooefff76e2021-12-15 16:51:30 -05003287// TODO: Any action the adapter needs to do following a onu adapter inter adapter service restart?
3288func (dh *DeviceHandler) onuInterAdapterRestarted(ctx context.Context, endPoint string) error {
3289 logger.Warnw(ctx, "onu-inter-adapter-service-reconnected", log.Fields{"endpoint": endPoint})
khenaidoo106c61a2021-08-11 18:05:46 -04003290 return nil
3291}
3292
khenaidooefff76e2021-12-15 16:51:30 -05003293// getOnuInterAdapterServiceClientHandler is used to setup the remote gRPC service
3294func (dh *DeviceHandler) getOnuInterAdapterServiceClientHandler(ctx context.Context, conn *grpc.ClientConn) interface{} {
3295 if conn == nil {
khenaidoo106c61a2021-08-11 18:05:46 -04003296 return nil
3297 }
khenaidooefff76e2021-12-15 16:51:30 -05003298 return onu_inter_adapter_service.NewOnuInterAdapterServiceClient(conn)
khenaidoo106c61a2021-08-11 18:05:46 -04003299}
Girish Gowdra950326e2021-11-05 12:43:24 -07003300
3301func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
3302 dh.lockDevice.Lock()
3303 defer dh.lockDevice.Unlock()
3304 dh.isDeviceDeletionInProgress = flag
3305}
3306
3307func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
3308 dh.lockDevice.RLock()
3309 defer dh.lockDevice.RUnlock()
3310 return dh.isDeviceDeletionInProgress
3311}
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08003312
3313// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
3314// Returns false if waiting timed out.
3315func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
3316 c := make(chan struct{})
3317 go func() {
3318 defer close(c)
3319 wg.Wait()
3320 }()
3321 select {
3322 case <-c:
3323 return true // completed normally
3324 case <-time.After(timeout):
3325 return false // timed out
3326 }
3327}