blob: f7d1405638d9104a2b88ca13defe21f7dfecf8de [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
Girish Gowdra491a9c62021-01-06 16:43:07 -080024 "errors"
cuilin20187b2a8c32019-03-26 19:52:28 -070025 "fmt"
26 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
Matteo Scandolo945e4012019-12-12 14:16:11 -080033 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070034 "github.com/gogo/protobuf/proto"
35 "github.com/golang/protobuf/ptypes"
Girish Kumar93e91742020-07-27 16:43:19 +000036 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
37 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070038 "github.com/opencord/voltha-lib-go/v5/pkg/adapters/adapterif"
39 "github.com/opencord/voltha-lib-go/v5/pkg/config"
40 "github.com/opencord/voltha-lib-go/v5/pkg/events/eventif"
41 flow_utils "github.com/opencord/voltha-lib-go/v5/pkg/flows"
42 "github.com/opencord/voltha-lib-go/v5/pkg/log"
43 "github.com/opencord/voltha-lib-go/v5/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080044
Thomas Lee S94109f12020-03-03 16:39:29 +053045 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080046 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070047 "github.com/opencord/voltha-protos/v4/go/common"
kesavand62126212021-01-12 04:56:06 -050048 "github.com/opencord/voltha-protos/v4/go/extension"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070049 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
50 of "github.com/opencord/voltha-protos/v4/go/openflow_13"
51 oop "github.com/opencord/voltha-protos/v4/go/openolt"
52 "github.com/opencord/voltha-protos/v4/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070053 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040054 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040055 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053056)
57
salmansiddiqui7ac62132019-08-22 03:58:50 +000058// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040059const (
Girish Gowdra491a9c62021-01-06 16:43:07 -080060 InvalidPort = 0xffffffff
61 MaxNumOfGroupHandlerChannels = 256
62
63 McastFlowOrGroupAdd = "McastFlowOrGroupAdd"
64 McastFlowOrGroupModify = "McastFlowOrGroupModify"
65 McastFlowOrGroupRemove = "McastFlowOrGroupRemove"
kesavand62126212021-01-12 04:56:06 -050066 oltPortInfoTimeout = 3
Manikkaraj kb1d51442019-07-23 10:41:02 -040067)
68
Phaneendra Manda4c62c802019-03-06 21:37:49 +053069//DeviceHandler will interact with the OLT device.
70type DeviceHandler struct {
Matteo Scandolodfa7a972020-11-06 13:03:40 -080071 cm *config.ConfigManager
cuilin20187b2a8c32019-03-26 19:52:28 -070072 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053073 coreProxy adapterif.CoreProxy
74 AdapterProxy adapterif.AdapterProxy
Himani Chawlacd407802020-12-10 12:08:59 +053075 EventProxy eventif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070076 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070077 exitChannel chan int
78 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053079 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070080 transitionMap *TransitionMap
81 clientCon *grpc.ClientConn
Girish Gowdra9602eb42020-09-09 15:50:39 -070082 flowMgr []*OpenOltFlowMgr
83 groupMgr *OpenOltGroupMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040084 eventMgr *OpenOltEventMgr
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070085 resourceMgr []*rsrcMgr.OpenOltResourceMgr
86
87 deviceInfo *oop.DeviceInfo
Naga Manjunatha8dc9372019-10-31 23:01:18 +053088
Girish Gowdra3ab6d212020-03-24 17:33:15 -070089 discOnus sync.Map
90 onus sync.Map
91 portStats *OpenOltStatisticsMgr
92 metrics *pmmetrics.PmMetrics
93 stopCollector chan bool
94 stopHeartbeatCheck chan bool
95 activePorts sync.Map
96 stopIndications chan bool
97 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -070098
Mahir Gunyelb0046752021-02-26 13:51:05 -080099 totalPonPorts uint32
100 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
101 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800102
103 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
104 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
Girish Gowdrada69ec12021-11-16 15:04:58 -0800105 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
106 stopMcastHandlerRoutine []chan bool
107 mcastHandlerRoutineActive []bool
Gamze Abakac2c32a62021-03-11 11:44:18 +0000108
109 adapterPreviouslyConnected bool
110 agentPreviouslyConnected bool
Girish Gowdra1cd96d82021-11-05 09:56:26 -0700111
112 isDeviceDeletionInProgress bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700113}
114
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700116type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700117 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700118 deviceType string
119 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700120 onuID uint32
121 intfID uint32
122 proxyDeviceID string
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530123 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400124 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700125}
126
Mahir Gunyelb0046752021-02-26 13:51:05 -0800127type onuIndicationMsg struct {
128 ctx context.Context
129 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800130}
131
132type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800133 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800134 stopChannel chan struct{}
135}
136
Girish Gowdra491a9c62021-01-06 16:43:07 -0800137//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
138//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
139//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
140//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
141type McastFlowOrGroupControlBlock struct {
142 ctx context.Context // Flow/group handler context
143 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
144 flow *voltha.OfpFlowStats // Flow message (can be nil or valid flow)
145 group *voltha.OfpGroupEntry // Group message (can be nil or valid group)
146 errChan *chan error // channel to report the mcast Flow/group handling error
147}
148
Naga Manjunath7615e552019-10-11 22:35:47 +0530149var pmNames = []string{
150 "rx_bytes",
151 "rx_packets",
152 "rx_mcast_packets",
153 "rx_bcast_packets",
154 "tx_bytes",
155 "tx_packets",
156 "tx_mcast_packets",
157 "tx_bcast_packets",
158}
159
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700160//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530161func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700162 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700163 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700164 device.deviceType = deviceTp
165 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700166 device.onuID = onuID
167 device.intfID = intfID
168 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530169 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700170 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530171}
172
173//NewDeviceHandler creates a new device handler
Himani Chawlacd407802020-12-10 12:08:59 +0530174func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep eventif.EventProxy, device *voltha.Device, adapter *OpenOLT, cm *config.ConfigManager) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700175 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800176 dh.cm = cm
cuilin20187b2a8c32019-03-26 19:52:28 -0700177 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400178 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400179 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700180 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700181 dh.device = cloned
182 dh.openOLT = adapter
183 dh.exitChannel = make(chan int, 1)
184 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530185 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530186 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530187 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 -0500188 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400189 dh.stopIndications = make(chan bool, 1)
Mahir Gunyelb0046752021-02-26 13:51:05 -0800190 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800191 // Create a slice of buffered channels for handling concurrent mcast flow/group.
192 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdrada69ec12021-11-16 15:04:58 -0800193 dh.stopMcastHandlerRoutine = make([]chan bool, MaxNumOfGroupHandlerChannels)
194 dh.mcastHandlerRoutineActive = make([]bool, MaxNumOfGroupHandlerChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800195 for i := range dh.incomingMcastFlowOrGroup {
196 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
Girish Gowdrada69ec12021-11-16 15:04:58 -0800197 dh.stopMcastHandlerRoutine[i] = make(chan bool, 1)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800198 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
199 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
200 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
201 // for incoming mcast flow/group to be processed serially.
Girish Gowdrada69ec12021-11-16 15:04:58 -0800202 dh.mcastHandlerRoutineActive[i] = true
203 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
Girish Gowdra491a9c62021-01-06 16:43:07 -0800204 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700205 //TODO initialize the support classes.
206 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530207}
208
209// start save the device to the data model
210func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700211 dh.lockDevice.Lock()
212 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000213 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700214 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000215 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530216}
217
218// stop stops the device dh. Not much to do for now
219func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700220 dh.lockDevice.Lock()
221 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000222 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700223 dh.exitChannel <- 1
Neha Sharma96b7bf22020-06-15 10:37:32 +0000224 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530225}
226
ssiddiqui5dcd2312021-08-23 21:58:25 +0530227func (dh *DeviceHandler) getPonTechnology(intfID uint32) string {
228 for _, resourceRanges := range dh.deviceInfo.GetRanges() {
229 for _, pooledIntfID := range resourceRanges.GetIntfIds() {
230 if pooledIntfID == intfID {
231 return resourceRanges.GetTechnology()
232 }
233 }
234 }
235 return ""
236}
237
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400238func macifyIP(ip net.IP) string {
239 if len(ip) > 0 {
240 oct1 := strconv.FormatInt(int64(ip[12]), 16)
241 oct2 := strconv.FormatInt(int64(ip[13]), 16)
242 oct3 := strconv.FormatInt(int64(ip[14]), 16)
243 oct4 := strconv.FormatInt(int64(ip[15]), 16)
244 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
245 }
246 return ""
247}
248
Neha Sharma96b7bf22020-06-15 10:37:32 +0000249func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400250 var genmac string
251 var addr net.IP
252 var ips []string
253 var err error
254
Neha Sharma96b7bf22020-06-15 10:37:32 +0000255 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400256
257 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000258 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400259
260 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000261 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400262 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000263 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400264 }
265 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000266 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530267 log.Fields{"host": ips[0],
268 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400269 return genmac, nil
270 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000271 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400272 }
273
274 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000275 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530276 log.Fields{"host": host,
277 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400278 return genmac, nil
279}
280
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530281func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700282 slist := strings.Split(mac, ":")
283 result := make([]uint32, len(slist))
284 var err error
285 var tmp int64
286 for index, val := range slist {
287 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
288 return []uint32{1, 2, 3, 4, 5, 6}
289 }
290 result[index] = uint32(tmp)
291 }
292 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530293}
294
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700295//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 -0800296func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530297
David K. Bainbridge794735f2020-02-11 21:01:37 -0800298 switch portType {
299 case voltha.Port_ETHERNET_NNI:
300 return fmt.Sprintf("nni-%d", portNum), nil
301 case voltha.Port_PON_OLT:
302 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700303 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800304
Girish Kumarf26e4882020-03-05 06:49:10 +0000305 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530306}
307
Neha Sharma96b7bf22020-06-15 10:37:32 +0000308func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000309 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700310 if state == "up" {
311 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500312 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500313 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700314 } else {
315 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500316 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700317 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700318 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400319 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800320 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000321 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400322 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500323
Neha Sharma8f4e4322020-08-06 10:51:53 +0000324 if port, err := dh.coreProxy.GetDevicePort(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, portNum); err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000325 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
Neha Sharma8f4e4322020-08-06 10:51:53 +0000326 if err := dh.coreProxy.PortStateUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, portType, portNum, operStatus); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400327 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
328 "device-id": dh.device.Id,
329 "port-type": portType,
330 "port-number": portNum,
331 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500332 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400333 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500334 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400335 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700336 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400337 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700338 PortNo: portNum,
339 Label: label,
340 Type: portType,
341 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700342 OfpPort: &of.OfpPort{
343 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
344 Config: 0,
345 State: uint32(of.OfpPortState_OFPPS_LIVE),
346 Curr: capacity,
347 Advertised: capacity,
348 Peer: capacity,
349 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
350 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
351 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700352 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000353 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700354 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000355 if err := dh.coreProxy.PortCreated(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000356 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800357 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000358 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400359 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000360 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530361 return nil
362}
363
Kent Hagermane6ff1012020-07-14 15:07:53 -0400364func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +0000365 device, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530366 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400367 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
368 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530369 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800370 dh.lockDevice.Lock()
371 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530372 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530373}
374
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700375// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530376// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800377func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000378 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700379 defer func() {
380 dh.lockDevice.Lock()
381 dh.isReadIndicationRoutineActive = false
382 dh.lockDevice.Unlock()
383 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700384 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700385 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700386 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700387 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400388
David Bainbridgef5879ca2019-12-13 21:17:54 +0000389 // Create an exponential backoff around re-enabling indications. The
390 // maximum elapsed time for the back off is set to 0 so that we will
391 // continue to retry. The max interval defaults to 1m, but is set
392 // here for code clarity
393 indicationBackoff := backoff.NewExponentialBackOff()
394 indicationBackoff.MaxElapsedTime = 0
395 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700396
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700397 dh.lockDevice.Lock()
398 dh.isReadIndicationRoutineActive = true
399 dh.lockDevice.Unlock()
400
Girish Gowdra3f974912020-03-23 20:35:18 -0700401Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700402 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400403 select {
404 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000405 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700406 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400407 default:
408 indication, err := indications.Recv()
409 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000410 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530411 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530412 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400413 // Use an exponential back off to prevent getting into a tight loop
414 duration := indicationBackoff.NextBackOff()
415 if duration == backoff.Stop {
416 // If we reach a maximum then warn and reset the backoff
417 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000418 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530419 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530420 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400421 indicationBackoff.Reset()
422 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700423
424 // On failure process a backoff timer while watching for stopIndications
425 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700426 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700427 select {
428 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000429 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700430 if !backoffTimer.Stop() {
431 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700432 }
433 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700434 case <-backoffTimer.C:
435 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700436 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700437 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
438 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400439 }
440 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000441 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530442 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000443 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530444 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530445 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700446 // Close the stream, and re-initialize it
447 if err = indications.CloseSend(); err != nil {
448 // Ok to ignore here, because we landed here due to a problem on the stream
449 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000450 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530451 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530452 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700453 }
Matteo Scandolof16389e2021-05-18 00:47:08 +0000454 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700455 return err
456 }
457 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400458 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530459 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400460 // Reset backoff if we have a successful receive
461 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400462 // When OLT is admin down, ignore all indications.
Girish Gowdra852ad912021-05-04 00:05:50 -0700463 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000464 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530465 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530466 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400467 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400468 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400469 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700470 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700471 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700472 // Close the send stream
473 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700474
Girish Gowdra3f974912020-03-23 20:35:18 -0700475 return nil
476}
477
478func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700479 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700480 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
481 if err != nil {
482 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
483 }
484 if indications == nil {
485 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
486 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700487 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700488 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400489}
490
491// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
492func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
493 switch indication.Data.(type) {
494 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
495 return true
496
497 default:
498 return false
499 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700500}
501
David K. Bainbridge794735f2020-02-11 21:01:37 -0800502func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700503 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000504 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530505 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700506 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530507 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700508 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000509 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000510 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530511 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000512 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800513 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000514 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800515 }
516 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700517}
518
David K. Bainbridge794735f2020-02-11 21:01:37 -0800519// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530520func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700521 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700522 switch indication.Data.(type) {
523 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000524 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
525 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700526 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 -0800527 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400528 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800529 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700530 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000531 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
532 defer span.Finish()
533
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700534 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800535 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000536 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400537 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800538 }
539 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000540 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000542 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
543 defer span.Finish()
544
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700545 intfOperInd := indication.GetIntfOperInd()
546 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800547 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000548 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400549 _ = 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 -0800550 }
551 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700552 } else if intfOperInd.GetType() == "pon" {
553 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
554 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800555 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000556 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400557 _ = 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 -0800558 }
559 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700561 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000562 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530563 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530564 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700565 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000566 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
567 defer span.Finish()
568
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700569 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000570 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800571 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800572 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700573 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000574 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
575 defer span.Finish()
576
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000578 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800579 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800580 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700581 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000582 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
583 defer span.Finish()
584
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700585 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000586 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 -0800587 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000588 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400589 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800590 }
591 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700592 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000593 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
594 defer span.Finish()
595
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700596 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000597 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700598 "intf-type": pktInd.IntfId,
599 "intf-id": pktInd.IntfId,
600 "gem-port-id": pktInd.GemportId,
601 "port-no": pktInd.PortNo,
602 "device-id": dh.device.Id,
603 })
604
605 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000606 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700607 "intf-type": pktInd.IntfId,
608 "intf-id": pktInd.IntfId,
609 "gem-port-id": pktInd.GemportId,
610 "port-no": pktInd.PortNo,
611 "packet": hex.EncodeToString(pktInd.Pkt),
612 "device-id": dh.device.Id,
613 })
614 }
615
David K. Bainbridge794735f2020-02-11 21:01:37 -0800616 go func() {
617 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400618 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800619 }
620 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700621 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000622 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
623 defer span.Finish()
624
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700625 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700626 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700627 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000628 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
629 defer span.Finish()
630
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700631 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000632 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000634 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
635 defer span.Finish()
636
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700637 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000638 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
639 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700640 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530641}
642
643// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530644func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530645 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000646 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530647
Girish Gowdrada69ec12021-11-16 15:04:58 -0800648 // instantiate the mcast handler routines.
649 for i := range dh.incomingMcastFlowOrGroup {
650 // We land inside the below "if" code path, after the OLT comes back from a reboot, otherwise the routines
651 // are already active when the DeviceHandler module is first instantiated (as part of Adopt_device RPC invocation).
652 if !dh.mcastHandlerRoutineActive[i] {
653 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
654 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
655 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
656 // for incoming mcast flow/group to be processed serially.
657 dh.mcastHandlerRoutineActive[i] = true
658 go dh.mcastFlowOrGroupChannelHandlerRoutine(i, dh.incomingMcastFlowOrGroup[i], dh.stopMcastHandlerRoutine[i])
659 }
660 }
661
Girish Gowdru0c588b22019-04-23 23:24:56 -0400662 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530663 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400664 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000665 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400666 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000667
668 //Clear olt communication failure event
669 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
670 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700671 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000672 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
673
Gamze Abakac2c32a62021-03-11 11:44:18 +0000674 //check adapter and agent reconcile status
675 //reboot olt if needed (olt disconnection case)
676 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
677 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
678 log.Fields{
679 "device-id": dh.device.Id,
680 "adapter-status": dh.adapterPreviouslyConnected,
681 "agent-status": dh.agentPreviouslyConnected,
682 })
683 _ = dh.RebootDevice(ctx, dh.device)
684 }
685
Girish Gowdru0c588b22019-04-23 23:24:56 -0400686 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530687}
688
689// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530690func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000691 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400692
npujarec5762e2020-01-01 14:08:48 +0530693 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400694 if err != nil || device == nil {
695 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000696 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400697 }
698
699 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400700
701 //Update the device oper state and connection status
702 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800703 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400704 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800705 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400706
David K. Bainbridge794735f2020-02-11 21:01:37 -0800707 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000708 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400709 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400710
711 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530712 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400713 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000714 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400715 }
716 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400717 // Update onu state as down in onu adapter
718 onuInd := oop.OnuIndication{}
719 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800720 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +0300721 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800722 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400723 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +0300724 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800725 "onu-indicator": onuInd,
726 "device-type": onuDevice.Type,
727 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700728 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800729 } else {
730 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 -0700731 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400732 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800733 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700734 /* Discovered ONUs entries need to be cleared , since after OLT
735 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530736 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800737 dh.lockDevice.Unlock()
738
Neha Sharma96b7bf22020-06-15 10:37:32 +0000739 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700740 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530741}
742
743// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530744func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400745 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000746
747 // if the connection is already available, close the previous connection (olt reboot case)
748 if dh.clientCon != nil {
749 if err = dh.clientCon.Close(); err != nil {
750 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
751 } else {
752 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
753 }
754 }
755
756 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000757 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
758 grpc.WithInsecure(),
759 grpc.WithBlock(),
760 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000761 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000762 )),
763 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000764 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000765 )))
766
767 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530768 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530769 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000770 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400771 }
772 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530773}
774
775// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530776func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400777 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530778 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400779 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530780}
781
782// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530783func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530784 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000785 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400786
787 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530788 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
789 if err != nil || device == nil {
790 /*TODO: needs to handle error scenarios */
791 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
792 }
793 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000794 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400795
796 cloned := proto.Clone(device).(*voltha.Device)
797 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
798 cloned.OperStatus = voltha.OperStatus_UNKNOWN
799 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530800 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
801 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 -0400802 }
803
Chaitrashree G S44124192019-08-07 20:21:36 -0400804 // 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 +0530805 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400806 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530807 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400808 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400809 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
810 // all the modules initialized and ready to handle incoming ONUs.
811
Thomas Lee S985938d2020-05-04 11:40:41 +0530812 err = dh.initializeDeviceHandlerModules(ctx)
813 if err != nil {
814 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 -0400815 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400816
817 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800818 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530819 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400820 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800821 }
822 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700823
824 go startHeartbeatCheck(ctx, dh)
825
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400826 return nil
827 }
828
Neha Sharma8f4e4322020-08-06 10:51:53 +0000829 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400830 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400831 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400832 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400833 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400834 dh.populateActivePorts(ctx, ports)
835 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
836 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400837 }
838
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400839 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530840 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 -0400841 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530842
cuilin20187b2a8c32019-03-26 19:52:28 -0700843 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800844 go func() {
845 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400846 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800847 }
848 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000850
851 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000852 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000853 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700854
855 go startHeartbeatCheck(ctx, dh)
856
cuilin20187b2a8c32019-03-26 19:52:28 -0700857 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530858}
859
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400860func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700861 var err error
862 dh.deviceInfo, err = dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400863
864 if err != nil {
865 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
866 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700867 dh.totalPonPorts = dh.deviceInfo.GetPonPorts()
868 dh.agentPreviouslyConnected = dh.deviceInfo.PreviouslyConnected
Girish Gowdra9602eb42020-09-09 15:50:39 -0700869
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700870 dh.resourceMgr = make([]*rsrcMgr.OpenOltResourceMgr, dh.totalPonPorts)
Girish Gowdra9602eb42020-09-09 15:50:39 -0700871 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700872 var i uint32
873 for i = 0; i < dh.totalPonPorts; i++ {
874 // Instantiate resource manager
875 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 -0700876 return olterrors.ErrResourceManagerInstantiating
877 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400878 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700879 // GroupManager instance is per OLT. But it needs a reference to any instance of resourceMgr to interface with
880 // the KV store to manage mcast group data. Provide the first instance (0th index)
881 if dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr[0]); dh.groupMgr == nil {
882 return olterrors.ErrGroupManagerInstantiating
883 }
884 for i = 0; i < dh.totalPonPorts; i++ {
885 // Instantiate flow manager
886 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr[i], dh.groupMgr, i); dh.flowMgr[i] == nil {
887 return olterrors.ErrFlowManagerInstantiating
888 }
889 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400890 /* TODO: Instantiate Alarm , stats , BW managers */
891 /* Instantiating Event Manager to handle Alarms and KPIs */
892 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
893
894 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000895 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400896
897 return nil
898
899}
900
Neha Sharma96b7bf22020-06-15 10:37:32 +0000901func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400902 var err error
903 var deviceInfo *oop.DeviceInfo
904
Neha Sharma8f4e4322020-08-06 10:51:53 +0000905 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400906
907 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000908 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400909 }
910 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000911 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400912 }
913
Neha Sharma96b7bf22020-06-15 10:37:32 +0000914 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400915 dh.device.Root = true
916 dh.device.Vendor = deviceInfo.Vendor
917 dh.device.Model = deviceInfo.Model
918 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
919 dh.device.HardwareVersion = deviceInfo.HardwareVersion
920 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
921
922 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000923 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400924 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000925 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400926 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000927 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400928 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000929 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400930 dh.device.MacAddress = genmac
931 } else {
932 dh.device.MacAddress = deviceInfo.DeviceId
933 }
934
935 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000936 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000937 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400938 }
939
940 return deviceInfo, nil
941}
942
Neha Sharma96b7bf22020-06-15 10:37:32 +0000943func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -0700944 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530945 for {
946 select {
947 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000948 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530949 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000950 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700951
Neha Sharma8f4e4322020-08-06 10:51:53 +0000952 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400953 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700954 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "err": err})
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400955 continue
956 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530957 for _, port := range ports {
958 // NNI Stats
959 if port.Type == voltha.Port_ETHERNET_NNI {
960 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
961 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000962 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000963 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000964 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530965 }
966 // PON Stats
967 if port.Type == voltha.Port_PON_OLT {
968 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
969 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
970 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000971 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000972 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530973 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000974 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000975
Girish Gowdrabcf98af2021-07-01 08:24:42 -0700976 onuGemInfoLst := dh.flowMgr[intfID].getOnuGemInfoList(ctx)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700977 if len(onuGemInfoLst) > 0 {
978 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfoLst)
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000979 }
Chaitrashree G Sef088112020-02-03 21:39:27 -0500980 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530981 }
982 }
983 }
984}
985
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700986//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530987func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400988 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000989 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530990 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530991
992 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400993 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
994 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530995 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530996}
997
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700998//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530999func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -07001000 return &ic.SwitchCapability{
1001 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +05301002 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -07001003 HwDesc: "open_pon",
1004 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001005 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -07001006 },
1007 SwitchFeatures: &of.OfpSwitchFeatures{
1008 NBuffers: 256,
1009 NTables: 2,
1010 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
1011 of.OfpCapabilities_OFPC_TABLE_STATS |
1012 of.OfpCapabilities_OFPC_PORT_STATS |
1013 of.OfpCapabilities_OFPC_GROUP_STATS),
1014 },
1015 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301016}
1017
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001018// GetInterAdapterTechProfileDownloadMessage fetches the TechProfileDownloadMessage for the caller.
1019func (dh *DeviceHandler) GetInterAdapterTechProfileDownloadMessage(ctx context.Context, tpPath string, ponPortNum uint32, onuID uint32, uniID uint32) *ic.InterAdapterTechProfileDownloadMessage {
1020 ifID, err := IntfIDFromPonPortNum(ctx, ponPortNum)
1021 if err != nil {
1022 return nil
1023 }
1024 return dh.flowMgr[ifID].getTechProfileDownloadMessage(ctx, tpPath, ifID, onuID, uniID)
1025}
1026
Neha Sharma96b7bf22020-06-15 10:37:32 +00001027func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
1028 logger.Debugw(ctx, "omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001029 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001030 var deviceID string
1031 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -07001032
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001033 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -07001034 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 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 -07001036 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
1037 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001038
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001039 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301040
1041 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
1042
Neha Sharma96b7bf22020-06-15 10:37:32 +00001043 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})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001044 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001045 kwargs := make(map[string]interface{})
1046 kwargs["onu_id"] = omciInd.OnuId
1047 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -07001048
Neha Sharma8f4e4322020-08-06 10:51:53 +00001049 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001050 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301051 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001052 "intf-id": omciInd.IntfId,
1053 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001054 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001055 deviceType = onuDevice.Type
1056 deviceID = onuDevice.Id
1057 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
1058 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301059 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001060 } else {
1061 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001062 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 +05301063 deviceType = onuInCache.(*OnuDevice).deviceType
1064 deviceID = onuInCache.(*OnuDevice).deviceID
1065 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -07001066 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001067
1068 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +00001069 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001070 ic.InterAdapterMessageType_OMCI_REQUEST, dh.openOLT.config.Topic, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301072 return olterrors.NewErrCommunication("omci-request", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001073 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001074 "destination": deviceType,
1075 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001076 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001077 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001078 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301079}
1080
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001081//ProcessInterAdapterMessage sends the proxied messages to the target device
1082// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1083// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
1085 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001086 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001087 return dh.handleInterAdapterOmciMsg(ctx, msg)
1088 }
1089 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
1090}
cuilin20187b2a8c32019-03-26 19:52:28 -07001091
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001092func (dh *DeviceHandler) handleInterAdapterOmciMsg(ctx context.Context, msg *ic.InterAdapterMessage) error {
1093 msgID := msg.Header.Id
1094 fromTopic := msg.Header.FromTopic
1095 toTopic := msg.Header.ToTopic
1096 toDeviceID := msg.Header.ToDeviceId
1097 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -07001098
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001099 logger.Debugw(ctx, "omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -07001100
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001101 msgBody := msg.GetBody()
1102
1103 omciMsg := &ic.InterAdapterOmciMessage{}
1104 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
1105 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
1106 }
1107
1108 if omciMsg.GetProxyAddress() == nil {
1109 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
1110 if err != nil {
1111 return olterrors.NewErrNotFound("onu", log.Fields{
1112 "device-id": dh.device.Id,
1113 "onu-device-id": toDeviceID}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001114 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001115 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1116 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
1117 return olterrors.NewErrCommunication("send-failed", log.Fields{
1118 "device-id": dh.device.Id,
1119 "onu-device-id": toDeviceID}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001120 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001121 } else {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001122 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1123 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
1124 return olterrors.NewErrCommunication("send-failed", log.Fields{
1125 "device-id": dh.device.Id,
1126 "onu-device-id": toDeviceID}, err)
1127 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001128 }
1129 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301130}
1131
Neha Sharma96b7bf22020-06-15 10:37:32 +00001132func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133 var intfID uint32
1134 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001135 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001136 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001137 intfID = onuDevice.ProxyAddress.GetChannelId()
1138 onuID = onuDevice.ProxyAddress.GetOnuId()
1139 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001140 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001141 intfID = omciMsg.GetProxyAddress().GetChannelId()
1142 onuID = omciMsg.GetProxyAddress().GetOnuId()
1143 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001144 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001145 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001146 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 -08001147
Thomas Lee S94109f12020-03-03 16:39:29 +05301148 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001149 "intf-id": intfID,
1150 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001151 }
1152
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001153 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1154 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001155 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001156 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1157 hex.Encode(hexPkt, omciMsg.Message)
1158 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1159
1160 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1161 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1162 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001163 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001164 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001165
Neha Sharma8f4e4322020-08-06 10:51:53 +00001166 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001167 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301168 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001169 "intf-id": intfID,
1170 "onu-id": onuID,
1171 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001174}
1175
David K. Bainbridge794735f2020-02-11 21:01:37 -08001176func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301177 logger.Debugw(ctx, "activate-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id, "OmccEncryption": dh.openOLT.config.OmccEncryption})
Girish Gowdra37f13fa2021-08-16 10:59:45 -07001178 if err := dh.flowMgr[intfID].AddOnuInfoToFlowMgrCacheAndKvStore(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001179 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001180 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001181 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301182 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301183 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001184 st, _ := status.FromError(err)
1185 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001186 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1187
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001188 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301189 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001190 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001191 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001192 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001193 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001194 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001195}
1196
Mahir Gunyelb0046752021-02-26 13:51:05 -08001197func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001198 channelID := onuDiscInd.GetIntfId()
1199 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001200
Mahir Gunyelb0046752021-02-26 13:51:05 -08001201 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001202 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301203
cuilin20187b2a8c32019-03-26 19:52:28 -07001204 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001205 if sn != "" {
1206 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001207 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001208 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001209 }
1210
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301211 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001212 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001213 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301214
1215 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1216 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1217 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1218 OnuLosRaise event sent for it */
1219 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1220 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1221 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001222 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301223 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1224 "currentIntfId": onuDiscInd.GetIntfId()})
1225 // TODO:: Should we need to ignore raising OnuLosClear event
1226 // when onu connected to different PON?
1227 }
1228 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1229 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1230 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001231 go func() {
1232 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001233 logger.Debugw(ctx, "indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001234 }
1235 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301236 }
1237 return true
1238 })
1239
Neha Sharma96b7bf22020-06-15 10:37:32 +00001240 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001241 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001242 }
1243
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001244 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001245
1246 // check the ONU is already know to the OLT
1247 // NOTE the second time the ONU is discovered this should return a device
1248 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1249
1250 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001251 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 -08001252 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001253 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 -08001254 switch e.Code() {
1255 case codes.Internal:
1256 // this probably means NOT FOUND, so just create a new device
1257 onuDevice = nil
1258 case codes.DeadlineExceeded:
1259 // if the call times out, cleanup and exit
1260 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001261 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001262 }
1263 }
1264 }
1265
1266 if onuDevice == nil {
1267 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001268 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001269 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001270 ponintfid := onuDiscInd.GetIntfId()
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001271 onuID, err = dh.resourceMgr[ponintfid].GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001272
Neha Sharma96b7bf22020-06-15 10:37:32 +00001273 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001274
1275 if err != nil {
1276 // if we can't create an ID in resource manager,
1277 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001278 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001279 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001280 "pon-intf-id": ponintfid,
1281 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001282 }
1283
Neha Sharma8f4e4322020-08-06 10:51:53 +00001284 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001285 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001286 dh.discOnus.Delete(sn)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001287 dh.resourceMgr[ponintfid].FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301288 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001289 "pon-intf-id": ponintfid,
1290 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001291 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001292 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 -07001293 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001294 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001295 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301296 log.Fields{"onuDevice": onuDevice,
1297 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001298 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301299 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001300 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001301
1302 // we can now use the existing ONU Id
1303 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001304 //Insert the ONU into cache to use in OnuIndication.
1305 //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 +00001306 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001307 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301308 "intfId": onuDiscInd.GetIntfId(),
1309 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001310 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001311
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301312 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301313 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001314 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301315 log.Fields{"onu": onuDev,
1316 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001317
Kent Hagermane6ff1012020-07-14 15:07:53 -04001318 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301319 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001320 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001321 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001322 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001323 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001324 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301325 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001327 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001328 }
1329 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001330}
1331
Mahir Gunyelb0046752021-02-26 13:51:05 -08001332func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001333
1334 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001335 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001336 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001337 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001338 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001339 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301340 log.Fields{"onuId": onuInd.OnuId,
1341 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301342 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001343 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001344 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301345
David K. Bainbridge794735f2020-02-11 21:01:37 -08001346 errFields := log.Fields{"device-id": dh.device.Id}
1347
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301348 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1349
Mahir Gunyele77977b2019-06-27 05:36:22 -07001350 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1351 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001352 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001353 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001354 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001355 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1356 if serialNumber != "" {
1357 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001358 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001359 } else {
1360 kwargs["onu_id"] = onuInd.OnuId
1361 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 errFields["onu-id"] = onuInd.OnuId
1363 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001364 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001365 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001366 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001367
David K. Bainbridge794735f2020-02-11 21:01:37 -08001368 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001369 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001370 }
1371
David K. Bainbridge794735f2020-02-11 21:01:37 -08001372 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001373 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001374 "previousIntfId": onuDevice.ParentPortNo,
1375 "currentIntfId": ponPort})
1376 }
1377
1378 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001379 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301380 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1381 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301382 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 }
1384 if !foundInCache {
1385 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1386
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301387 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001388
1389 }
kesavand7cf3a052020-08-28 12:49:18 +05301390 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001391 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001392 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"err": err})
kesavand7cf3a052020-08-28 12:49:18 +05301393 }
1394 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001395 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001396 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397 }
1398 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001399}
1400
Neha Sharma96b7bf22020-06-15 10:37:32 +00001401func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001402 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 -07001403 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1404 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1405 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1406 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001407 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001408 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1409 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001410 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001411 onuInd.OperState = "down"
1412 }
1413 }
1414
David K. Bainbridge794735f2020-02-11 21:01:37 -08001415 switch onuInd.OperState {
1416 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001417 logger.Debugw(ctx, "sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001418 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301419 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001420 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001421 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301422 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001423 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001424 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001425 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001426 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001428 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001429 logger.Debugw(ctx, "sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Matt Jeanneret53539512019-07-20 14:47:02 -04001430 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301431 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001432 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001433 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301434 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001435 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001436 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001437 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001438 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001439 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001440 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001441 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001442 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001443 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001444}
1445
cuilin20187b2a8c32019-03-26 19:52:28 -07001446func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1447 if serialNum != nil {
1448 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001449 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001450 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001451}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001452func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1453 decodedStr, err := hex.DecodeString(serialNum[4:])
1454 if err != nil {
1455 return nil, err
1456 }
1457 return &oop.SerialNumber{
1458 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001459 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001460 }, nil
1461}
cuilin20187b2a8c32019-03-26 19:52:28 -07001462
1463func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001464 if len(vendorSpecific) > 3 {
1465 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1466 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1467 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1468 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1469 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1470 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1471 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1472 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1473 return tmp
1474 }
1475 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001476}
1477
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001478//UpdateFlowsBulk upates the bulk flow
1479func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301480 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001481}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001482
1483//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001484func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1485 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301486 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001487 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301488 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001489 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001490 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001491 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001492 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001493 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001494 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001495 "intf-id": parentPort,
1496 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001497 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001498 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 -08001499 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301500}
1501
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001502// SendPacketInToCore sends packet-in to core
1503// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1504// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001505func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001506 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001507 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001508 "port": logicalPort,
1509 "packet": hex.EncodeToString(packetPayload),
1510 "device-id": dh.device.Id,
1511 })
1512 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001513 if err := dh.coreProxy.SendPacketIn(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301514 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001515 "source": "adapter",
1516 "destination": "core",
1517 "device-id": dh.device.Id,
1518 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001519 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001520 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001521 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001522 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001523 "packet": hex.EncodeToString(packetPayload),
1524 "device-id": dh.device.Id,
1525 })
1526 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001527 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001528}
1529
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001530// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001531func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001532 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001533
1534 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1535 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001536 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001537 }
1538
Kent Hagermane6ff1012020-07-14 15:07:53 -04001539 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001540 metrics := dh.metrics.GetSubscriberMetrics()
1541 for _, m := range pmConfigs.Metrics {
1542 metrics[m.Name].Enabled = m.Enabled
1543
1544 }
1545 }
1546}
1547
Girish Gowdrada69ec12021-11-16 15:04:58 -08001548func (dh *DeviceHandler) handleFlows(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, flowMetadata *voltha.FlowMetadata) []error {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001549 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001550 var errorsList []error
1551
Girish Gowdra1cd96d82021-11-05 09:56:26 -07001552 if dh.getDeviceDeletionInProgressFlag() {
1553 // The device itself is going to be reset as part of deletion. So nothing to be done.
1554 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1555 return nil
1556 }
1557
Girish Gowdru0c588b22019-04-23 23:24:56 -04001558 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001559 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001560 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001561
Neha Sharma96b7bf22020-06-15 10:37:32 +00001562 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301563 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001564 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301565 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001566 if flow_utils.HasGroup(flow) {
1567 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1568 } else {
1569 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1570 }
Girish Gowdracefae192020-03-19 18:14:10 -07001571 if err != nil {
1572 errorsList = append(errorsList, err)
1573 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001574 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301575
1576 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001577 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001578 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301579 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001580 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301581 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001582 if flow_utils.HasGroup(flow) {
1583 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1584 } else {
Girish Gowdrada69ec12021-11-16 15:04:58 -08001585 if dh.flowMgr == nil || dh.flowMgr[ponIf] == nil {
1586 // The flow manager module could be uninitialized if the flow arrives too soon before the device has reconciled fully
1587 logger.Errorw(ctx, "flow-manager-uninitialized", log.Fields{"device-id": device.Id})
1588 err = fmt.Errorf("flow-manager-uninitialized-%v", device.Id)
1589 } else {
1590 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1591 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08001592 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001593 if err != nil {
1594 errorsList = append(errorsList, err)
1595 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301596 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001597 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001598
Girish Gowdrada69ec12021-11-16 15:04:58 -08001599 return errorsList
1600}
1601
1602func (dh *DeviceHandler) handleGroups(ctx context.Context, groups *of.FlowGroupChanges) []error {
1603 var err error
1604 var errorsList []error
1605
1606 if dh.getDeviceDeletionInProgressFlag() {
1607 // The device itself is going to be reset as part of deletion. So nothing to be done.
1608 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
1609 return nil
1610 }
1611
Girish Gowdracefae192020-03-19 18:14:10 -07001612 // 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 +00001613 if groups != nil {
1614 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001615 // err = dh.groupMgr.AddGroup(ctx, group)
1616 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001617 if err != nil {
1618 errorsList = append(errorsList, err)
1619 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001620 }
1621 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001622 // err = dh.groupMgr.ModifyGroup(ctx, group)
1623 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001624 if err != nil {
1625 errorsList = append(errorsList, err)
1626 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001627 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001628 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001629 // err = dh.groupMgr.DeleteGroup(ctx, group)
1630 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001631 if err != nil {
1632 errorsList = append(errorsList, err)
1633 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001634 }
1635 }
Girish Gowdrada69ec12021-11-16 15:04:58 -08001636
1637 return errorsList
1638}
1639
1640//UpdateFlowsIncrementally updates the device flow
1641func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
1642
1643 var errorsList []error
1644
1645 if dh.getDeviceDeletionInProgressFlag() {
1646 // The device itself is going to be reset as part of deletion. So nothing to be done.
1647 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": device.Id})
1648 return nil
1649 }
1650
1651 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
1652 errorsList = append(errorsList, dh.handleFlows(ctx, device, flows, flowMetadata)...)
1653 errorsList = append(errorsList, dh.handleGroups(ctx, groups)...)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001654 if len(errorsList) > 0 {
1655 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1656 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001657 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001658 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301659}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001660
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001661//DisableDevice disables the given device
1662//It marks the following for the given device:
1663//Device-Handler Admin-State : down
1664//Device Port-State: UNKNOWN
1665//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001666func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001667 /* On device disable ,admin state update has to be done prior sending request to agent since
1668 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001669 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001670 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001671 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001672 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001673 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001674 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001675 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001676 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001677 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001678 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301679
1680 dh.discOnus = sync.Map{}
1681 dh.onus = sync.Map{}
1682
Thomas Lee S85f37312020-04-03 17:06:12 +05301683 //stopping the stats collector
1684 dh.stopCollector <- true
1685
Neha Sharma96b7bf22020-06-15 10:37:32 +00001686 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001687 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301688 //Update device Admin state
1689 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001690 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
Neha Sharma8f4e4322020-08-06 10:51:53 +00001691 if err := dh.coreProxy.PortsStateUpdate(log.WithSpanFromContext(context.TODO(), ctx), cloned.Id, ^uint32(1<<voltha.Port_PON_OLT), voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001692 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001693 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001694 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001695 return nil
1696}
1697
Neha Sharma96b7bf22020-06-15 10:37:32 +00001698func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001699 // Update onu state as unreachable in onu adapter
1700 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301701 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001702 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001703 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001704 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001705 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 -04001706 }
1707 if onuDevices != nil {
1708 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001709 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001710 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001711 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001712 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001713 "From Adapter": dh.openOLT.config.Topic, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001714 }
1715
1716 }
1717 }
1718
1719}
1720
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001721//ReenableDevice re-enables the olt device after disable
1722//It marks the following for the given device:
1723//Device-Handler Admin-State : up
1724//Device Port-State: ACTIVE
1725//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001727 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301728 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001729 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301730 }
1731 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001732 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001733
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001734 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001735
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001736 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1737 if err != nil {
divyadesai3af43e12020-08-18 07:10:54 +00001738 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001739 }
1740 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001741 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001742 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001743 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001744 device.OperStatus = voltha.OperStatus_ACTIVE
1745 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001746
Neha Sharma8f4e4322020-08-06 10:51:53 +00001747 if err := dh.coreProxy.DeviceStateUpdate(log.WithSpanFromContext(context.TODO(), ctx), device.Id, device.ConnectStatus, device.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301748 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001749 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001750 "connect-status": device.ConnectStatus,
1751 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001752 }
kesavand39e0aa32020-01-28 20:58:50 -05001753
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001755
1756 return nil
1757}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001758
npujarec5762e2020-01-01 14:08:48 +05301759func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001760 var uniID uint32
1761 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301762 for _, port := range onu.UniPorts {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001763 uniID = UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001764 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001765 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001766 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001767 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001768 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001769 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001770 tpIDList := dh.resourceMgr[onu.IntfID].GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001771 for _, tpID := range tpIDList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001772 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001773 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001774 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001775 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001776 if err = dh.resourceMgr[onu.IntfID].RemoveMeterInfoForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001777 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001778 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301780 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001781 dh.resourceMgr[onu.IntfID].FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1782 if err = dh.resourceMgr[onu.IntfID].RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001783 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301784 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001785 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001786 if err = dh.resourceMgr[onu.IntfID].DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001787 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 +00001788 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001789 }
1790 return nil
1791}
1792
Devmalya Paul495b94a2019-08-27 19:42:00 -04001793// 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 +05301794func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001795 logger.Debugw(ctx, "function-entry-delete-device", log.Fields{"device-id": dh.device.Id})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001796 /* Clear the KV store data associated with the all the UNI ports
1797 This clears up flow data and also resource map data for various
1798 other pon resources like alloc_id and gemport_id
1799 */
Girish Gowdra1cd96d82021-11-05 09:56:26 -07001800
1801 dh.setDeviceDeletionInProgressFlag(true)
Girish Gowdrada69ec12021-11-16 15:04:58 -08001802 var wg sync.WaitGroup
1803 wg.Add(1) // for the mcast routine below to finish
1804 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
1805 for _, flMgr := range dh.flowMgr {
1806 wg.Add(1) // for the flow handler routine below to finish
1807 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
1808 }
1809 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
1810 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
1811 } else {
1812 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
1813 }
Girish Gowdra1cd96d82021-11-05 09:56:26 -07001814
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001815 dh.cleanupDeviceResources(ctx)
1816 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 -04001817 // Stop the Stats collector
1818 dh.stopCollector <- true
1819 // stop the heartbeat check routine
1820 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301821 dh.lockDevice.RLock()
1822 // Stop the read indication only if it the routine is active
1823 if dh.isReadIndicationRoutineActive {
1824 dh.stopIndications <- true
1825 }
1826 dh.lockDevice.RUnlock()
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001827 dh.removeOnuIndicationChannels(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001828 //Reset the state
1829 if dh.Client != nil {
1830 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301831 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001832 }
1833 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07001834 // There is no need to update the core about operation status and connection status of the OLT.
1835 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1836 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1837 // because the device does not exist in DB.
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001838
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001839 return nil
1840}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001841func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001842
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001843 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301844 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001845 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001846 var err error
Girish Gowdrabcf98af2021-07-01 08:24:42 -07001847 onuGemData := dh.flowMgr[ponPort].getOnuGemInfoList(ctx)
Andrey Pozolotin32b36562021-06-02 10:23:26 +03001848 for i, onu := range onuGemData {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrey Pozolotin32b36562021-06-02 10:23:26 +03001850 if err = dh.clearUNIData(ctx, &onuGemData[i]); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001851 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301852 }
1853 }
Girish Gowdra1cd96d82021-11-05 09:56:26 -07001854 _ = dh.resourceMgr[ponPort].DeleteAllFlowIDsForGemForIntf(ctx, ponPort)
1855 _ = dh.resourceMgr[ponPort].DeleteAllOnuGemInfoForIntf(ctx, ponPort)
1856
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07001857 if err := dh.resourceMgr[ponPort].Delete(ctx, ponPort); err != nil {
1858 logger.Debug(ctx, err)
1859 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001860 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001861 }
A R Karthick1f85b802019-10-11 05:06:05 +00001862
Devmalya Paul495b94a2019-08-27 19:42:00 -04001863 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301864 dh.onus.Range(func(key interface{}, value interface{}) bool {
1865 dh.onus.Delete(key)
1866 return true
1867 })
1868
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001869 /*Delete discovered ONU map for the device*/
1870 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1871 dh.discOnus.Delete(key)
1872 return true
1873 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001874}
1875
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001876//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001877func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001878 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301879 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001880 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001881 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001882 return nil
1883}
1884
David K. Bainbridge794735f2020-02-11 21:01:37 -08001885func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001886 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001887 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001888 "packet-indication": *packetIn,
1889 "device-id": dh.device.Id,
1890 "packet": hex.EncodeToString(packetIn.Pkt),
1891 })
1892 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001893 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001894 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001895 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001896 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001897 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001898 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001899 "logical-port-num": logicalPortNum,
1900 "device-id": dh.device.Id,
1901 "packet": hex.EncodeToString(packetIn.Pkt),
1902 })
1903 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001904
Neha Sharma8f4e4322020-08-06 10:51:53 +00001905 if err := dh.coreProxy.SendPacketIn(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301906 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001907 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301908 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001909 "device-id": dh.device.Id,
1910 "packet": hex.EncodeToString(packetIn.Pkt),
1911 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001912 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001913
Matteo Scandolo92186242020-06-12 10:54:18 -07001914 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001915 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001916 "packet": hex.EncodeToString(packetIn.Pkt),
1917 "device-id": dh.device.Id,
1918 })
1919 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001920 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001921}
1922
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001923// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301924func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001925 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001926 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001927 "device-id": dh.device.Id,
1928 "egress-port-no": egressPortNo,
1929 "pkt-length": len(packet.Data),
1930 "packet": hex.EncodeToString(packet.Data),
1931 })
1932 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001933
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001934 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001935 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001936 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1937 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301938 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1939 // Do not packet-out lldp packets on uni port.
1940 // ONOS has no clue about uni/nni ports, it just packets out on all
1941 // available ports on the Logical Switch. It should not be interested
1942 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001943 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001944 "device-id": dh.device.Id,
1945 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301946 return nil
1947 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001948 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1949 if innerEthType == 0x8100 {
1950 // q-in-q 802.1ad or 802.1q double tagged packet.
1951 // slice out the outer tag.
1952 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001953 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001954 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001955 "packet-data": hex.EncodeToString(packet.Data),
1956 "device-id": dh.device.Id,
1957 })
1958 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001959 }
1960 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001961 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1962 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001963 uniID := UniIDFromPortNum(uint32(egressPortNo))
1964
Girish Gowdra9602eb42020-09-09 15:50:39 -07001965 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001966 if err != nil {
1967 // In this case the openolt agent will receive the gemPortID as 0.
1968 // The agent tries to retrieve the gemPortID in this case.
1969 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001970 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001971 "intf-id": intfID,
1972 "onu-id": onuID,
1973 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001974 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301975 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001976 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001977 }
1978
1979 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07001980 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001981 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001982 "egress-port-no": egressPortNo,
1983 "intf-id": intfID,
1984 "onu-id": onuID,
1985 "uni-id": uniID,
1986 "gem-port-id": gemPortID,
1987 "packet": hex.EncodeToString(packet.Data),
1988 "device-id": dh.device.Id,
1989 })
1990 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001991
npujarec5762e2020-01-01 14:08:48 +05301992 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301993 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001994 "source": "adapter",
1995 "destination": "onu",
1996 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001997 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001998 "oni-id": onuID,
1999 "uni-id": uniID,
2000 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002001 "packet": hex.EncodeToString(packet.Data),
2002 "device-id": dh.device.Id,
2003 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002004 }
2005 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002006 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08002007 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002008 return olterrors.NewErrInvalidValue(log.Fields{
2009 "egress-nni-port": egressPortNo,
2010 "device-id": dh.device.Id,
2011 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002012 }
2013 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04002014
Matteo Scandolo92186242020-06-12 10:54:18 -07002015 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002016 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002017 "uplink-pkt": uplinkPkt,
2018 "packet": hex.EncodeToString(packet.Data),
2019 "device-id": dh.device.Id,
2020 })
2021 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04002022
npujarec5762e2020-01-01 14:08:48 +05302023 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002024 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
2025 "packet": hex.EncodeToString(packet.Data),
2026 "device-id": dh.device.Id,
2027 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002028 }
2029 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002030 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05302031 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002032 "egressPortType": egressPortType,
2033 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05302034 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08002035 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002036 }
2037 return nil
2038}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002039
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002040func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
2041 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07002042}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302043
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002044func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00002045
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302046 // start the heartbeat check towards the OLT.
2047 var timerCheck *time.Timer
2048
2049 for {
2050 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2051 select {
2052 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002053 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002054 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002055 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302056 if timerCheck == nil {
2057 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002058 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302059 }
2060 } else {
2061 if timerCheck != nil {
2062 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002063 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302064 }
2065 timerCheck = nil
2066 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002067 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302068 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302069 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302070 }
2071 cancel()
2072 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002073 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302074 return
2075 }
2076 }
2077}
2078
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002079func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
2080 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
2081 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002082 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2083 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2084 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2085 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2086 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002087 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002088 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2089 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002090 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302091
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002092 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2093 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002094 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
2095 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002096 _ = 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 -04002097 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002098 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002099 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002100 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002101
2102 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002103 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00002104 device.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2105 device.OperStatus = voltha.OperStatus_UNKNOWN
2106 go dh.eventMgr.oltCommunicationEvent(ctx, device, raisedTs)
2107
Girish Gowdrab8f1b5a2021-06-27 20:42:40 -07002108 dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002109 // Stop the Stats collector
2110 dh.stopCollector <- true
2111 // stop the heartbeat check routine
2112 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002113
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002114 dh.lockDevice.RLock()
2115 // Stop the read indication only if it the routine is active
2116 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2117 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2118 // on next execution of the readIndication routine.
2119 if dh.isReadIndicationRoutineActive {
2120 dh.stopIndications <- true
2121 }
2122 dh.lockDevice.RUnlock()
2123
Girish Gowdrada69ec12021-11-16 15:04:58 -08002124 var wg sync.WaitGroup
2125 wg.Add(1) // for the multicast handler routine
2126 go dh.StopAllMcastHandlerRoutines(ctx, &wg)
2127 for _, flMgr := range dh.flowMgr {
2128 wg.Add(1) // for the flow handler routine
2129 go flMgr.StopAllFlowHandlerRoutines(ctx, &wg)
2130 }
2131 if !dh.waitForTimeoutOrCompletion(&wg, time.Second*30) {
2132 logger.Warnw(ctx, "timed out waiting for stopping flow and group handlers", log.Fields{"deviceID": device.Id})
2133 } else {
2134 logger.Infow(ctx, "all flow and group handlers shutdown gracefully", log.Fields{"deviceID": device.Id})
2135 }
Gamze Abakac2c32a62021-03-11 11:44:18 +00002136 //reset adapter reconcile flag
2137 dh.adapterPreviouslyConnected = false
2138
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002139 dh.transitionMap.Handle(ctx, DeviceInit)
2140
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302141 }
2142}
kesavand39e0aa32020-01-28 20:58:50 -05002143
2144// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002145func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2146 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2147 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002148}
2149
2150// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002151func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2152 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2153 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002154}
2155
kdarapu1afeceb2020-02-12 01:38:09 -05002156//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 +00002157func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2158 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002159 if port.GetType() == voltha.Port_ETHERNET_NNI {
2160 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002161 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302162 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302163 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002164 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002165 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002166 }
2167 // fetch interfaceid from PortNo
2168 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2169 ponIntf := &oop.Interface{IntfId: ponID}
2170 var operStatus voltha.OperStatus_Types
2171 if enablePort {
2172 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302173 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002174
2175 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302176 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002177 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002178 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002179 }
2180 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002181 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002182 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002183 } else {
2184 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302185 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002186 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302187 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002188 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002189 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002190 }
2191 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002192 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002193 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002194 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302195 if err := dh.coreProxy.PortStateUpdate(ctx, dh.device.Id, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302196 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302197 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002198 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002199 }
2200 return nil
2201}
2202
kdarapu1afeceb2020-02-12 01:38:09 -05002203//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002204func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002205 // Disable the port and update the oper_port_status to core
2206 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002207 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002208 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002209 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302210 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302211 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002212 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002213 }
2214 }
2215 }
2216 return nil
2217}
2218
2219//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002220func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2221 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2222 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002223 if port.Type == voltha.Port_ETHERNET_NNI {
2224 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002225 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002226 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002227 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002228 }
2229 }
2230 if port.Type == voltha.Port_PON_OLT {
2231 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002232 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002233 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002234 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002235 }
2236 }
2237 }
2238}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002239
2240// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002241func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002242 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002243 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2244 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002245
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002246 var sn *oop.SerialNumber
2247 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002248 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302249 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002250 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302251 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002252 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002253 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002254
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002255 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002256 //clear PON resources associated with ONU
2257 onuGem, err := dh.resourceMgr[intfID].GetOnuGemInfo(ctx, intfID, onuID)
2258 if err != nil || onuGem == nil || onuGem.OnuID != onuID {
2259 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
2260 "device-id": dh.device.Id,
2261 "intf-id": intfID,
2262 "onuID": onuID,
2263 "err": err})
2264 } else {
2265 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
2266 if err := dh.clearUNIData(ctx, onuGem); err != nil {
2267 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
2268 "device-id": dh.device.Id,
2269 "onu-device": onu,
2270 "err": err})
2271 }
2272 // Clear flowids for gem cache.
2273 for _, gem := range onuGem.GemPorts {
2274 dh.resourceMgr[intfID].DeleteFlowIDsForGem(ctx, intfID, gem)
2275 }
Girish Gowdra37f13fa2021-08-16 10:59:45 -07002276 if err := dh.flowMgr[intfID].RemoveOnuInfoFromFlowMgrCacheAndKvStore(ctx, intfID, onuID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002277 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
2278 "intf-id": intfID,
2279 "onu-device": onu,
2280 "onu-gem": onuGem,
2281 "err": err})
2282 //Not returning error on cleanup.
2283 }
2284 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGem})
2285 dh.resourceMgr[intfID].FreeonuID(ctx, intfID, []uint32{onuGem.OnuID})
2286 }
2287 dh.onus.Delete(onuKey)
2288 dh.discOnus.Delete(onuSn)
2289
2290 // Now clear the ONU on the OLT
Neha Sharma8f4e4322020-08-06 10:51:53 +00002291 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302292 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302293 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002294 "onu-id": onuID}, err).Log()
2295 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002296
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002297 return nil
2298}
Girish Gowdracefae192020-03-19 18:14:10 -07002299
2300func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002301 for _, field := range flow_utils.GetOfbFields(flow) {
2302 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002303 return field.GetPort()
2304 }
2305 }
2306 return InvalidPort
2307}
2308
2309func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002310 for _, action := range flow_utils.GetActions(flow) {
2311 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002312 if out := action.GetOutput(); out != nil {
2313 return out.GetPort()
2314 }
2315 }
2316 }
2317 return InvalidPort
2318}
2319
Girish Gowdracefae192020-03-19 18:14:10 -07002320func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2321 inPort := getInPortFromFlow(flow)
2322 outPort := getOutPortFromFlow(flow)
2323
2324 if inPort == InvalidPort || outPort == InvalidPort {
2325 return inPort, outPort
2326 }
2327
2328 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2329 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2330 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002331 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002332 return uniPort, outPort
2333 }
2334 }
2335 } else {
2336 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2337 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002338 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002339 return inPort, uniPort
2340 }
2341 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2342 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002343 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002344 return uniPort, outPort
2345 }
2346 }
2347 }
2348
2349 return InvalidPort, InvalidPort
2350}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002351
2352func extractOmciTransactionID(omciPkt []byte) uint16 {
2353 if len(omciPkt) > 3 {
2354 d := omciPkt[0:2]
2355 transid := binary.BigEndian.Uint16(d)
2356 return transid
2357 }
2358 return 0
2359}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002360
2361// StoreOnuDevice stores the onu parameters to the local cache.
2362func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2363 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2364 dh.onus.Store(onuKey, onuDevice)
2365}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002366
Neha Sharma8f4e4322020-08-06 10:51:53 +00002367func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002368 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002369 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002370 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002371 resp := new(voltha.ReturnValues)
2372 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002373 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002374 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002375 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2376 return nil, err
2377 }
2378 ID = device.ProxyAddress.GetOnuId()
2379 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2380 valueparam.Onu = &Onu
2381 valueparam.Value = value
2382
2383 // This API is unsupported until agent patch is added
2384 resp.Unsupported = uint32(value)
2385 _ = ctx
2386
2387 // Uncomment this code once agent changes are complete and tests
2388 /*
2389 resp, err = dh.Client.GetValue(ctx, valueparam)
2390 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002391 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "err": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002392 return nil, err
2393 }
2394 */
2395
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002396 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 -08002397 return resp, nil
2398}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002399
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002400func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002401 // Default to PON0
2402 var intfID uint32
2403 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002404 if inPort != InvalidPort && outPort != InvalidPort {
2405 _, intfID, _, _ = ExtractAccessFromFlow(inPort, outPort)
2406 }
2407 return intfID
2408}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002409
Mahir Gunyelb0046752021-02-26 13:51:05 -08002410func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2411 dh.perPonOnuIndicationChannelLock.Lock()
2412 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2413 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002414 return ch.indicationChannel
2415 }
2416 channels := onuIndicationChannels{
2417 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002418 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002419 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002420 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002421 stopChannel: make(chan struct{}),
2422 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002423 dh.perPonOnuIndicationChannel[intfID] = channels
2424 dh.perPonOnuIndicationChannelLock.Unlock()
2425 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002426 return channels.indicationChannel
2427
2428}
2429
Mahir Gunyelb0046752021-02-26 13:51:05 -08002430func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2431 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2432 dh.perPonOnuIndicationChannelLock.Lock()
2433 defer dh.perPonOnuIndicationChannelLock.Unlock()
2434 for _, v := range dh.perPonOnuIndicationChannel {
2435 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002436 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002437 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002438}
2439
Mahir Gunyelb0046752021-02-26 13:51:05 -08002440func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2441 ind := onuIndicationMsg{
2442 ctx: ctx,
2443 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002444 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002445 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002446 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002447 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002448}
2449
Mahir Gunyelb0046752021-02-26 13:51:05 -08002450func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002451 for {
2452 select {
2453 // process one indication per onu, before proceeding to the next one
2454 case onuInd := <-onuChannels.indicationChannel:
2455 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Mahir Gunyelb0046752021-02-26 13:51:05 -08002456 "ind": onuInd.indication})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002457 switch onuInd.indication.Data.(type) {
2458 case *oop.Indication_OnuInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002459 if err := dh.onuIndication(onuInd.ctx, onuInd.indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002460 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2461 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002462 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002463 }
2464 case *oop.Indication_OnuDiscInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002465 if err := dh.onuDiscIndication(onuInd.ctx, onuInd.indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002466 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2467 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002468 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002469 }
2470 }
2471 case <-onuChannels.stopChannel:
2472 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2473 close(onuChannels.indicationChannel)
2474 return
2475 }
2476 }
2477}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002478
2479// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2480// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
2481func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *voltha.OfpFlowStats, group *voltha.OfpGroupEntry, action string) error {
Girish Gowdrada69ec12021-11-16 15:04:58 -08002482 if dh.getDeviceDeletionInProgressFlag() {
2483 // The device itself is going to be reset as part of deletion. So nothing to be done.
2484 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": dh.device.Id})
2485 return nil
2486 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002487 // Step1 : Fill McastFlowOrGroupControlBlock
2488 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2489 // Step3 : Wait on response channel for response
2490 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002491 startTime := time.Now()
Girish Gowdra491a9c62021-01-06 16:43:07 -08002492 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2493 errChan := make(chan error)
2494 var groupID uint32
2495 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2496 ctx: ctx,
2497 flowOrGroupAction: action,
2498 flow: flow,
2499 group: group,
2500 errChan: &errChan,
2501 }
2502 if flow != nil {
2503 groupID = flow_utils.GetGroup(flow)
2504 } else if group != nil {
2505 groupID = group.Desc.GroupId
2506 } else {
2507 return errors.New("flow-and-group-both-nil")
2508 }
Girish Gowdrada69ec12021-11-16 15:04:58 -08002509 mcastRoutineIdx := groupID % MaxNumOfGroupHandlerChannels
2510 if dh.mcastHandlerRoutineActive[mcastRoutineIdx] {
2511 // Derive the appropriate go routine to handle the request by a simple module operation.
2512 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2513 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2514 // Wait for handler to return error value
2515 err := <-errChan
2516 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"err": err, "totalTimeInSeconds": time.Since(startTime).Milliseconds()})
2517 return err
2518 }
2519 logger.Errorw(ctx, "mcast handler routine not active for onu", log.Fields{"mcastRoutineIdx": mcastRoutineIdx})
2520 return fmt.Errorf("mcast-handler-routine-not-active-for-index-%v", mcastRoutineIdx)
Girish Gowdra491a9c62021-01-06 16:43:07 -08002521}
2522
2523// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
Girish Gowdrada69ec12021-11-16 15:04:58 -08002524func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(routineIndex int, mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock, stopHandler chan bool) {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002525 for {
Girish Gowdrada69ec12021-11-16 15:04:58 -08002526 select {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002527 // block on the channel to receive an incoming mcast flow/group
2528 // process the flow completely before proceeding to handle the next flow
Girish Gowdrada69ec12021-11-16 15:04:58 -08002529 case mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel:
2530 if mcastFlowOrGroupCb.flow != nil {
2531 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2532 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2533 log.Fields{"device-id": dh.device.Id,
2534 "flowToAdd": mcastFlowOrGroupCb.flow})
2535 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2536 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2537 // Pass the return value over the return channel
2538 *mcastFlowOrGroupCb.errChan <- err
2539 } else { // flow remove
2540 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2541 log.Fields{"device-id": dh.device.Id,
2542 "flowToRemove": mcastFlowOrGroupCb.flow})
2543 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2544 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2545 // Pass the return value over the return channel
2546 *mcastFlowOrGroupCb.errChan <- err
2547 }
2548 } else { // mcast group
2549 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2550 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2551 log.Fields{"device-id": dh.device.Id,
2552 "groupToAdd": mcastFlowOrGroupCb.group})
2553 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2554 // Pass the return value over the return channel
2555 *mcastFlowOrGroupCb.errChan <- err
2556 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2557 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2558 log.Fields{"device-id": dh.device.Id,
2559 "groupToModify": mcastFlowOrGroupCb.group})
2560 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2561 // Pass the return value over the return channel
2562 *mcastFlowOrGroupCb.errChan <- err
2563 } else { // group remove
2564 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2565 log.Fields{"device-id": dh.device.Id,
2566 "groupToRemove": mcastFlowOrGroupCb.group})
2567 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2568 // Pass the return value over the return channel
2569 *mcastFlowOrGroupCb.errChan <- err
2570 }
Girish Gowdra491a9c62021-01-06 16:43:07 -08002571 }
Girish Gowdrada69ec12021-11-16 15:04:58 -08002572 case <-stopHandler:
2573 dh.mcastHandlerRoutineActive[routineIndex] = false
2574 return
2575 }
2576 }
2577}
2578
2579// StopAllMcastHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
2580func (dh *DeviceHandler) StopAllMcastHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
2581 for i, v := range dh.stopMcastHandlerRoutine {
2582 if dh.mcastHandlerRoutineActive[i] {
2583 select {
2584 case v <- true:
2585 case <-time.After(time.Second * 5):
2586 logger.Warnw(ctx, "timeout stopping mcast handler routine", log.Fields{"idx": i, "deviceID": dh.device.Id})
Girish Gowdra491a9c62021-01-06 16:43:07 -08002587 }
2588 }
2589 }
Girish Gowdrada69ec12021-11-16 15:04:58 -08002590 wg.Done()
2591 logger.Debug(ctx, "stopped all mcast handler routines")
Girish Gowdra491a9c62021-01-06 16:43:07 -08002592}
kesavand62126212021-01-12 04:56:06 -05002593
2594func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2595
2596 singleValResp := extension.SingleGetValueResponse{
2597 Response: &extension.GetValueResponse{
2598 Response: &extension.GetValueResponse_PortCoutners{
2599 PortCoutners: &extension.GetOltPortCountersResponse{},
2600 },
2601 },
2602 }
2603
2604 errResp := func(status extension.GetValueResponse_Status,
2605 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2606 return &extension.SingleGetValueResponse{
2607 Response: &extension.GetValueResponse{
2608 Status: status,
2609 ErrReason: reason,
2610 },
2611 }
2612 }
2613
2614 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2615 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2616 //send error response
2617 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2618 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2619 }
2620 statIndChn := make(chan bool, 1)
2621 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2622 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2623 //request openOlt agent to send the the port statistics indication
2624
2625 go func() {
2626 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2627 if err != nil {
2628 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2629 }
2630 }()
2631 select {
2632 case <-statIndChn:
2633 //indication received for ports stats
2634 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2635 case <-time.After(oltPortInfoTimeout * time.Second):
2636 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2637 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2638 case <-ctx.Done():
2639 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2640 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2641 }
2642 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2643 //get nni stats
2644 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
2645 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2646 cmnni := dh.portStats.collectNNIMetrics(intfID)
2647 if cmnni == nil {
2648 //TODO define the error reason
2649 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2650 }
2651 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2652 return &singleValResp
2653
2654 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2655 // get pon stats
2656 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
2657 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2658 cmpon := dh.portStats.collectPONMetrics(intfID)
2659 if cmpon == nil {
2660 //TODO define the error reason
2661 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2662 }
2663 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2664 return &singleValResp
2665 }
2666 }
2667 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2668}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +05302669
2670func (dh *DeviceHandler) getOnuPonCounters(ctx context.Context, onuPonInfo *extension.GetOnuCountersRequest) *extension.SingleGetValueResponse {
2671
2672 singleValResp := extension.SingleGetValueResponse{
2673 Response: &extension.GetValueResponse{
2674 Response: &extension.GetValueResponse_OnuPonCounters{
2675 OnuPonCounters: &extension.GetOnuCountersResponse{},
2676 },
2677 },
2678 }
2679
2680 errResp := func(status extension.GetValueResponse_Status,
2681 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2682 return &extension.SingleGetValueResponse{
2683 Response: &extension.GetValueResponse{
2684 Status: status,
2685 ErrReason: reason,
2686 },
2687 }
2688 }
2689 intfID := onuPonInfo.IntfId
2690 onuID := onuPonInfo.OnuId
2691 onuKey := dh.formOnuKey(intfID, onuID)
2692
2693 if _, ok := dh.onus.Load(onuKey); !ok {
2694 logger.Errorw(ctx, "get-onui-pon-counters-request-invalid-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2695 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2696 }
2697 logger.Debugw(ctx, "get-onui-pon-counters-request-received", log.Fields{"intfID": intfID, "onuID": onuID})
2698 cmnni := dh.portStats.collectOnDemandOnuStats(ctx, intfID, onuID)
2699 if cmnni == nil {
2700 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2701 }
2702 dh.portStats.updateGetOnuPonCountersResponse(ctx, &singleValResp, cmnni)
2703 return &singleValResp
2704
2705}
Gamze Abaka85e9a142021-05-26 13:41:39 +00002706
2707func (dh *DeviceHandler) getRxPower(ctx context.Context, rxPowerRequest *extension.GetRxPowerRequest) *extension.SingleGetValueResponse {
2708
2709 Onu := oop.Onu{IntfId: rxPowerRequest.IntfId, OnuId: rxPowerRequest.OnuId}
2710 rxPower, err := dh.Client.GetPonRxPower(ctx, &Onu)
2711 if err != nil {
2712 logger.Errorw(ctx, "error-while-getting-rx-power", log.Fields{"Onu": Onu, "err": err})
2713 return generateSingleGetValueErrorResponse(err)
2714 }
2715 return &extension.SingleGetValueResponse{
2716 Response: &extension.GetValueResponse{
2717 Status: extension.GetValueResponse_OK,
2718 Response: &extension.GetValueResponse_RxPower{
2719 RxPower: &extension.GetRxPowerResponse{
2720 IntfId: rxPowerRequest.IntfId,
2721 OnuId: rxPowerRequest.OnuId,
2722 Status: rxPower.Status,
2723 FailReason: rxPower.FailReason.String(),
2724 RxPower: rxPower.RxPowerMeanDbm,
2725 },
2726 },
2727 },
2728 }
2729}
2730
2731func generateSingleGetValueErrorResponse(err error) *extension.SingleGetValueResponse {
2732 errResp := func(status extension.GetValueResponse_Status,
2733 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2734 return &extension.SingleGetValueResponse{
2735 Response: &extension.GetValueResponse{
2736 Status: status,
2737 ErrReason: reason,
2738 },
2739 }
2740 }
2741
2742 if err != nil {
2743 if e, ok := status.FromError(err); ok {
2744 switch e.Code() {
2745 case codes.Internal:
2746 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2747 case codes.DeadlineExceeded:
2748 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2749 case codes.Unimplemented:
2750 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_UNSUPPORTED)
2751 case codes.NotFound:
2752 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_DEVICE)
2753 }
2754 }
2755 }
2756
2757 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_REASON_UNDEFINED)
2758}
Girish Gowdra1cd96d82021-11-05 09:56:26 -07002759
2760func (dh *DeviceHandler) setDeviceDeletionInProgressFlag(flag bool) {
2761 dh.lockDevice.Lock()
2762 defer dh.lockDevice.Unlock()
2763 dh.isDeviceDeletionInProgress = flag
2764}
2765
2766func (dh *DeviceHandler) getDeviceDeletionInProgressFlag() bool {
2767 dh.lockDevice.RLock()
2768 defer dh.lockDevice.RUnlock()
2769 return dh.isDeviceDeletionInProgress
2770}
Girish Gowdrada69ec12021-11-16 15:04:58 -08002771
2772// waitForTimeoutOrCompletion waits for the waitgroup for the specified max timeout.
2773// Returns false if waiting timed out.
2774func (dh *DeviceHandler) waitForTimeoutOrCompletion(wg *sync.WaitGroup, timeout time.Duration) bool {
2775 c := make(chan struct{})
2776 go func() {
2777 defer close(c)
2778 wg.Wait()
2779 }()
2780 select {
2781 case <-c:
2782 return true // completed normally
2783 case <-time.After(timeout):
2784 return false // timed out
2785 }
2786}