blob: 1e860074c27c30204350ecaab841808ed3c1cd9c [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 Gowdraa09aeab2020-09-14 16:30:52 -070038 "github.com/opencord/voltha-lib-go/v4/pkg/adapters/adapterif"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080039 "github.com/opencord/voltha-lib-go/v4/pkg/config"
Himani Chawlacd407802020-12-10 12:08:59 +053040 "github.com/opencord/voltha-lib-go/v4/pkg/events/eventif"
Girish Gowdra491a9c62021-01-06 16:43:07 -080041 flow_utils "github.com/opencord/voltha-lib-go/v4/pkg/flows"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070042 "github.com/opencord/voltha-lib-go/v4/pkg/log"
43 "github.com/opencord/voltha-lib-go/v4/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
manikkaraj kbf256be2019-03-25 00:13:48 +053085 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053086
Girish Gowdra3ab6d212020-03-24 17:33:15 -070087 discOnus sync.Map
88 onus sync.Map
89 portStats *OpenOltStatisticsMgr
90 metrics *pmmetrics.PmMetrics
91 stopCollector chan bool
92 stopHeartbeatCheck chan bool
93 activePorts sync.Map
94 stopIndications chan bool
95 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -070096
Mahir Gunyelb0046752021-02-26 13:51:05 -080097 totalPonPorts uint32
98 perPonOnuIndicationChannel map[uint32]onuIndicationChannels
99 perPonOnuIndicationChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800100
101 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
102 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
103 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700104}
105
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700106//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109 deviceType string
110 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 onuID uint32
112 intfID uint32
113 proxyDeviceID string
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530114 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400115 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700116}
117
Mahir Gunyelb0046752021-02-26 13:51:05 -0800118type onuIndicationMsg struct {
119 ctx context.Context
120 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800121}
122
123type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800124 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800125 stopChannel chan struct{}
126}
127
Girish Gowdra491a9c62021-01-06 16:43:07 -0800128//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
129//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
130//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
131//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
132type McastFlowOrGroupControlBlock struct {
133 ctx context.Context // Flow/group handler context
134 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
135 flow *voltha.OfpFlowStats // Flow message (can be nil or valid flow)
136 group *voltha.OfpGroupEntry // Group message (can be nil or valid group)
137 errChan *chan error // channel to report the mcast Flow/group handling error
138}
139
Naga Manjunath7615e552019-10-11 22:35:47 +0530140var pmNames = []string{
141 "rx_bytes",
142 "rx_packets",
143 "rx_mcast_packets",
144 "rx_bcast_packets",
145 "tx_bytes",
146 "tx_packets",
147 "tx_mcast_packets",
148 "tx_bcast_packets",
149}
150
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700151//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530152func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700153 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700154 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700155 device.deviceType = deviceTp
156 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700157 device.onuID = onuID
158 device.intfID = intfID
159 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530160 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700161 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530162}
163
164//NewDeviceHandler creates a new device handler
Himani Chawlacd407802020-12-10 12:08:59 +0530165func 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 -0700166 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800167 dh.cm = cm
cuilin20187b2a8c32019-03-26 19:52:28 -0700168 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400169 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400170 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700171 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700172 dh.device = cloned
173 dh.openOLT = adapter
174 dh.exitChannel = make(chan int, 1)
175 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530176 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530177 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530178 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 -0500179 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400180 dh.stopIndications = make(chan bool, 1)
Mahir Gunyelb0046752021-02-26 13:51:05 -0800181 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800182 // Create a slice of buffered channels for handling concurrent mcast flow/group.
183 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
184 for i := range dh.incomingMcastFlowOrGroup {
185 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
186 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
187 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
188 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
189 // for incoming mcast flow/group to be processed serially.
190 go dh.mcastFlowOrGroupChannelHandlerRoutine(dh.incomingMcastFlowOrGroup[i])
191 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700192 //TODO initialize the support classes.
193 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530194}
195
196// start save the device to the data model
197func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700198 dh.lockDevice.Lock()
199 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000200 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700201 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000202 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530203}
204
205// stop stops the device dh. Not much to do for now
206func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700207 dh.lockDevice.Lock()
208 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000209 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700210 dh.exitChannel <- 1
Neha Sharma96b7bf22020-06-15 10:37:32 +0000211 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530212}
213
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400214func macifyIP(ip net.IP) string {
215 if len(ip) > 0 {
216 oct1 := strconv.FormatInt(int64(ip[12]), 16)
217 oct2 := strconv.FormatInt(int64(ip[13]), 16)
218 oct3 := strconv.FormatInt(int64(ip[14]), 16)
219 oct4 := strconv.FormatInt(int64(ip[15]), 16)
220 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
221 }
222 return ""
223}
224
Neha Sharma96b7bf22020-06-15 10:37:32 +0000225func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400226 var genmac string
227 var addr net.IP
228 var ips []string
229 var err error
230
Neha Sharma96b7bf22020-06-15 10:37:32 +0000231 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400232
233 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000234 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400235
236 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000237 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400238 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000239 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400240 }
241 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000242 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530243 log.Fields{"host": ips[0],
244 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400245 return genmac, nil
246 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000247 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400248 }
249
250 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000251 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530252 log.Fields{"host": host,
253 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400254 return genmac, nil
255}
256
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530257func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700258 slist := strings.Split(mac, ":")
259 result := make([]uint32, len(slist))
260 var err error
261 var tmp int64
262 for index, val := range slist {
263 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
264 return []uint32{1, 2, 3, 4, 5, 6}
265 }
266 result[index] = uint32(tmp)
267 }
268 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530269}
270
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700271//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 -0800272func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530273
David K. Bainbridge794735f2020-02-11 21:01:37 -0800274 switch portType {
275 case voltha.Port_ETHERNET_NNI:
276 return fmt.Sprintf("nni-%d", portNum), nil
277 case voltha.Port_PON_OLT:
278 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700279 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800280
Girish Kumarf26e4882020-03-05 06:49:10 +0000281 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530282}
283
Neha Sharma96b7bf22020-06-15 10:37:32 +0000284func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000285 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700286 if state == "up" {
287 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500288 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500289 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700290 } else {
291 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500292 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700293 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700294 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400295 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800296 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000297 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400298 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500299
Neha Sharma8f4e4322020-08-06 10:51:53 +0000300 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 +0000301 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
Neha Sharma8f4e4322020-08-06 10:51:53 +0000302 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 -0400303 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
304 "device-id": dh.device.Id,
305 "port-type": portType,
306 "port-number": portNum,
307 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500308 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400309 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500310 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400311 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700312 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400313 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700314 PortNo: portNum,
315 Label: label,
316 Type: portType,
317 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700318 OfpPort: &of.OfpPort{
319 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
320 Config: 0,
321 State: uint32(of.OfpPortState_OFPPS_LIVE),
322 Curr: capacity,
323 Advertised: capacity,
324 Peer: capacity,
325 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
326 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
327 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700328 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000329 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700330 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000331 if err := dh.coreProxy.PortCreated(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000332 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800333 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000334 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400335 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000336 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530337 return nil
338}
339
Kent Hagermane6ff1012020-07-14 15:07:53 -0400340func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +0000341 device, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530342 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400343 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
344 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530345 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800346 dh.lockDevice.Lock()
347 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530348 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530349}
350
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700351// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530352// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800353func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000354 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700355 defer func() {
356 dh.lockDevice.Lock()
357 dh.isReadIndicationRoutineActive = false
358 dh.lockDevice.Unlock()
359 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700360 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700361 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700362 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700363 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400364 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530365 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400366 if err != nil || device == nil {
367 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000368 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400369 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400370
David Bainbridgef5879ca2019-12-13 21:17:54 +0000371 // Create an exponential backoff around re-enabling indications. The
372 // maximum elapsed time for the back off is set to 0 so that we will
373 // continue to retry. The max interval defaults to 1m, but is set
374 // here for code clarity
375 indicationBackoff := backoff.NewExponentialBackOff()
376 indicationBackoff.MaxElapsedTime = 0
377 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700378
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700379 dh.lockDevice.Lock()
380 dh.isReadIndicationRoutineActive = true
381 dh.lockDevice.Unlock()
382
Girish Gowdra3f974912020-03-23 20:35:18 -0700383Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700384 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400385 select {
386 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000387 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700388 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400389 default:
390 indication, err := indications.Recv()
391 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000392 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530393 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530394 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400395 // Use an exponential back off to prevent getting into a tight loop
396 duration := indicationBackoff.NextBackOff()
397 if duration == backoff.Stop {
398 // If we reach a maximum then warn and reset the backoff
399 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000400 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530401 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530402 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400403 indicationBackoff.Reset()
404 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700405
406 // On failure process a backoff timer while watching for stopIndications
407 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700408 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700409 select {
410 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000411 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700412 if !backoffTimer.Stop() {
413 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700414 }
415 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700416 case <-backoffTimer.C:
417 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700418 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700419 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
420 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400421 }
422 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000423 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530424 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000425 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530426 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530427 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700428 // Close the stream, and re-initialize it
429 if err = indications.CloseSend(); err != nil {
430 // Ok to ignore here, because we landed here due to a problem on the stream
431 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000432 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530433 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530434 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700435 }
436 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
437 return err
438 }
439 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400440 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530441 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400442 // Reset backoff if we have a successful receive
443 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400444 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530445 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000446 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530447 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530448 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400449 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400450 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400451 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700452 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700453 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700454 // Close the send stream
455 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700456
Girish Gowdra3f974912020-03-23 20:35:18 -0700457 return nil
458}
459
460func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
461
462 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
463 if err != nil {
464 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
465 }
466 if indications == nil {
467 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
468 }
469
470 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400471}
472
473// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
474func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
475 switch indication.Data.(type) {
476 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
477 return true
478
479 default:
480 return false
481 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700482}
483
David K. Bainbridge794735f2020-02-11 21:01:37 -0800484func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000485 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000486 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530487 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700488 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530489 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000491 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000492 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530493 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000494 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800495 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000496 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800497 }
498 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700499}
500
David K. Bainbridge794735f2020-02-11 21:01:37 -0800501// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530502func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400503 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700504 switch indication.Data.(type) {
505 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000506 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
507 defer span.Finish()
508
David K. Bainbridge794735f2020-02-11 21:01:37 -0800509 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400510 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800511 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700512 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000513 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
514 defer span.Finish()
515
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700516 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800517 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000518 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400519 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800520 }
521 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000522 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700523 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000524 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
525 defer span.Finish()
526
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700527 intfOperInd := indication.GetIntfOperInd()
528 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800529 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000530 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400531 _ = 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 -0800532 }
533 }()
Kent Hagermane6ff1012020-07-14 15:07:53 -0400534 if err := dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId()); err != nil {
535 logger.Warn(ctx, err)
536 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700537 } else if intfOperInd.GetType() == "pon" {
538 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
539 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800540 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000541 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400542 _ = 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 -0800543 }
544 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000545 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700546 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000547 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530548 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530549 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700550 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000551 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
552 defer span.Finish()
553
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700554 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000555 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800556 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800557 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700558 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000559 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
560 defer span.Finish()
561
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700562 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000563 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800564 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800565 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700566 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000567 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
568 defer span.Finish()
569
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700570 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000571 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 -0800572 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000573 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400574 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800575 }
576 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000578 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
579 defer span.Finish()
580
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700581 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000582 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700583 "intf-type": pktInd.IntfId,
584 "intf-id": pktInd.IntfId,
585 "gem-port-id": pktInd.GemportId,
586 "port-no": pktInd.PortNo,
587 "device-id": dh.device.Id,
588 })
589
590 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000591 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700592 "intf-type": pktInd.IntfId,
593 "intf-id": pktInd.IntfId,
594 "gem-port-id": pktInd.GemportId,
595 "port-no": pktInd.PortNo,
596 "packet": hex.EncodeToString(pktInd.Pkt),
597 "device-id": dh.device.Id,
598 })
599 }
600
David K. Bainbridge794735f2020-02-11 21:01:37 -0800601 go func() {
602 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400603 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800604 }
605 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700606 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000607 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
608 defer span.Finish()
609
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700610 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700611 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700612 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000613 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
614 defer span.Finish()
615
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700616 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000617 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700618 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000619 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
620 defer span.Finish()
621
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700622 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000623 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
624 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700625 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530626}
627
628// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530629func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530630 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000631 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530632
Girish Gowdru0c588b22019-04-23 23:24:56 -0400633 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530634 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400635 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000636 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400637 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000638
639 //Clear olt communication failure event
640 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
641 dh.device.OperStatus = voltha.OperStatus_ACTIVE
642 raisedTs := time.Now().UnixNano()
643 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
644
Girish Gowdru0c588b22019-04-23 23:24:56 -0400645 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530646}
647
648// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530649func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000650 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400651
npujarec5762e2020-01-01 14:08:48 +0530652 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400653 if err != nil || device == nil {
654 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000655 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400656 }
657
658 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400659
660 //Update the device oper state and connection status
661 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800662 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400663 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800664 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400665
David K. Bainbridge794735f2020-02-11 21:01:37 -0800666 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000667 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400668 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400669
670 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530671 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400672 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000673 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400674 }
675 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400676 // Update onu state as down in onu adapter
677 onuInd := oop.OnuIndication{}
678 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800679 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +0300680 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800681 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400682 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +0300683 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800684 "onu-indicator": onuInd,
685 "device-type": onuDevice.Type,
686 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700687 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800688 } else {
689 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 -0700690 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400691 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800692 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700693 /* Discovered ONUs entries need to be cleared , since after OLT
694 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530695 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800696 dh.lockDevice.Unlock()
697
Neha Sharma96b7bf22020-06-15 10:37:32 +0000698 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700699 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530700}
701
702// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530703func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400704 var err error
Girish Kumar93e91742020-07-27 16:43:19 +0000705 // Use Intercepters to automatically inject and publish Open Tracing Spans by this GRPC client
706 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
707 grpc.WithInsecure(),
708 grpc.WithBlock(),
709 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000710 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000711 )),
712 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000713 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000714 )))
715
716 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530717 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530718 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000719 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400720 }
721 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530722}
723
724// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530725func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400726 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530727 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400728 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530729}
730
731// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530732func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530733 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000734 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400735
736 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530737 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
738 if err != nil || device == nil {
739 /*TODO: needs to handle error scenarios */
740 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
741 }
742 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000743 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400744
745 cloned := proto.Clone(device).(*voltha.Device)
746 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
747 cloned.OperStatus = voltha.OperStatus_UNKNOWN
748 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530749 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
750 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 -0400751 }
752
Chaitrashree G S44124192019-08-07 20:21:36 -0400753 // 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 +0530754 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400755 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530756 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400757 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400758 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
759 // all the modules initialized and ready to handle incoming ONUs.
760
Thomas Lee S985938d2020-05-04 11:40:41 +0530761 err = dh.initializeDeviceHandlerModules(ctx)
762 if err != nil {
763 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 -0400764 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400765
766 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800767 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530768 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400769 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800770 }
771 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700772
773 go startHeartbeatCheck(ctx, dh)
774
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400775 return nil
776 }
777
Neha Sharma8f4e4322020-08-06 10:51:53 +0000778 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400779 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400780 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400781 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400782 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400783 dh.populateActivePorts(ctx, ports)
784 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
785 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400786 }
787
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400788 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530789 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 -0400790 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530791
cuilin20187b2a8c32019-03-26 19:52:28 -0700792 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800793 go func() {
794 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400795 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800796 }
797 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000798 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000799
800 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000801 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000802 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700803
804 go startHeartbeatCheck(ctx, dh)
805
cuilin20187b2a8c32019-03-26 19:52:28 -0700806 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530807}
808
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400809func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000810 deviceInfo, err := dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400811
812 if err != nil {
813 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
814 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700815 dh.totalPonPorts = deviceInfo.GetPonPorts()
816
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400817 // Instantiate resource manager
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800818 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, deviceInfo, dh.cm.Backend.PathPrefix); dh.resourceMgr == nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400819 return olterrors.ErrResourceManagerInstantiating
820 }
821
Girish Gowdra9602eb42020-09-09 15:50:39 -0700822 dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400823
Girish Gowdra9602eb42020-09-09 15:50:39 -0700824 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
825 for i := range dh.flowMgr {
826 // Instantiate flow manager
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700827 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr, dh.groupMgr, uint32(i)); dh.flowMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700828 return olterrors.ErrResourceManagerInstantiating
829 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400830 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700831
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400832 /* TODO: Instantiate Alarm , stats , BW managers */
833 /* Instantiating Event Manager to handle Alarms and KPIs */
834 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
835
836 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000837 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400838
839 return nil
840
841}
842
Neha Sharma96b7bf22020-06-15 10:37:32 +0000843func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400844 var err error
845 var deviceInfo *oop.DeviceInfo
846
Neha Sharma8f4e4322020-08-06 10:51:53 +0000847 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400848
849 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000850 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400851 }
852 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000853 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400854 }
855
Neha Sharma96b7bf22020-06-15 10:37:32 +0000856 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400857 dh.device.Root = true
858 dh.device.Vendor = deviceInfo.Vendor
859 dh.device.Model = deviceInfo.Model
860 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
861 dh.device.HardwareVersion = deviceInfo.HardwareVersion
862 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
863
864 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000865 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400866 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000867 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400868 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000869 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400870 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000871 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400872 dh.device.MacAddress = genmac
873 } else {
874 dh.device.MacAddress = deviceInfo.DeviceId
875 }
876
877 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000878 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000879 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400880 }
881
882 return deviceInfo, nil
883}
884
Neha Sharma96b7bf22020-06-15 10:37:32 +0000885func startCollector(ctx context.Context, dh *DeviceHandler) {
886 logger.Debugf(ctx, "starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530887 for {
888 select {
889 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000890 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530891 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000892 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700893
Neha Sharma8f4e4322020-08-06 10:51:53 +0000894 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400895 if err != nil {
896 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
897 continue
898 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530899 for _, port := range ports {
900 // NNI Stats
901 if port.Type == voltha.Port_ETHERNET_NNI {
902 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
903 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000904 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000905 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000906 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530907 }
908 // PON Stats
909 if port.Type == voltha.Port_PON_OLT {
910 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
911 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
912 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000913 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000914 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530915 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000916 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000917
918 //ONU & Gem Stats
919 onuGemInfo := dh.flowMgr[intfID].onuGemInfo
920 if len(onuGemInfo) != 0 {
921 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfo)
922 }
Chaitrashree G Sef088112020-02-03 21:39:27 -0500923 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530924 }
925 }
926 }
927}
928
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700929//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530930func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400931 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000932 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530933 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530934
935 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400936 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
937 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530938 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530939}
940
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700941//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530942func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700943 return &ic.SwitchCapability{
944 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530945 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700946 HwDesc: "open_pon",
947 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700948 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -0700949 },
950 SwitchFeatures: &of.OfpSwitchFeatures{
951 NBuffers: 256,
952 NTables: 2,
953 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
954 of.OfpCapabilities_OFPC_TABLE_STATS |
955 of.OfpCapabilities_OFPC_PORT_STATS |
956 of.OfpCapabilities_OFPC_GROUP_STATS),
957 },
958 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530959}
960
Neha Sharma96b7bf22020-06-15 10:37:32 +0000961func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
962 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 -0700963 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700964 var deviceID string
965 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700966
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400967 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700968 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000969 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 -0700970 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
971 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400972
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700973 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530974
975 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
976
Neha Sharma96b7bf22020-06-15 10:37:32 +0000977 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 -0700978 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700979 kwargs := make(map[string]interface{})
980 kwargs["onu_id"] = omciInd.OnuId
981 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700982
Neha Sharma8f4e4322020-08-06 10:51:53 +0000983 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700984 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530985 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700986 "intf-id": omciInd.IntfId,
987 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700988 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700989 deviceType = onuDevice.Type
990 deviceID = onuDevice.Id
991 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
992 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530993 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700994 } else {
995 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +0000996 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 +0530997 deviceType = onuInCache.(*OnuDevice).deviceType
998 deviceID = onuInCache.(*OnuDevice).deviceID
999 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -07001000 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001001
1002 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +00001003 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001004 ic.InterAdapterMessageType_OMCI_REQUEST, dh.openOLT.config.Topic, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001005 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301006 return olterrors.NewErrCommunication("omci-request", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001007 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001008 "destination": deviceType,
1009 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001010 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001011 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001012 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301013}
1014
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001015//ProcessInterAdapterMessage sends the proxied messages to the target device
1016// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1017// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001018func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
1019 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001020 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -07001022 fromTopic := msg.Header.FromTopic
1023 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001024 toDeviceID := msg.Header.ToDeviceId
1025 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -07001026
Neha Sharma96b7bf22020-06-15 10:37:32 +00001027 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 -07001028
1029 msgBody := msg.GetBody()
1030
1031 omciMsg := &ic.InterAdapterOmciMessage{}
1032 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001033 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001034 }
1035
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001036 if omciMsg.GetProxyAddress() == nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001037 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001038 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301039 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001040 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001041 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001042 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001043 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1044 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301045 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001046 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001047 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001048 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001049 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001050 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1051 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301052 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001053 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001054 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001055 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001056 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001057 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001058 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001059 }
1060 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301061}
1062
Neha Sharma96b7bf22020-06-15 10:37:32 +00001063func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001064 var intfID uint32
1065 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001066 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001067 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001068 intfID = onuDevice.ProxyAddress.GetChannelId()
1069 onuID = onuDevice.ProxyAddress.GetOnuId()
1070 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001071 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001072 intfID = omciMsg.GetProxyAddress().GetChannelId()
1073 onuID = omciMsg.GetProxyAddress().GetOnuId()
1074 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001075 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001076 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001077 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 -08001078
Thomas Lee S94109f12020-03-03 16:39:29 +05301079 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001080 "intf-id": intfID,
1081 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001082 }
1083
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001084 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1085 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001086 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001087 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1088 hex.Encode(hexPkt, omciMsg.Message)
1089 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1090
1091 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1092 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1093 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001094 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001095 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001096
Neha Sharma8f4e4322020-08-06 10:51:53 +00001097 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001098 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301099 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001100 "intf-id": intfID,
1101 "onu-id": onuID,
1102 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001103 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001104 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001105}
1106
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301108 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 Gowdra9602eb42020-09-09 15:50:39 -07001109 if err := dh.flowMgr[intfID].UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001110 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001111 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001112 // TODO: need resource manager
1113 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301114 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301115 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001116 st, _ := status.FromError(err)
1117 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001118 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1119
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001120 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301121 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001122 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001123 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001124 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001125 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001127}
1128
Mahir Gunyelb0046752021-02-26 13:51:05 -08001129func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001130 channelID := onuDiscInd.GetIntfId()
1131 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001132
Mahir Gunyelb0046752021-02-26 13:51:05 -08001133 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001134 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301135
cuilin20187b2a8c32019-03-26 19:52:28 -07001136 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001137 if sn != "" {
1138 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001139 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001140 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001141 }
1142
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301143 var alarmInd oop.OnuAlarmIndication
1144 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001145 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301146
1147 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1148 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1149 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1150 OnuLosRaise event sent for it */
1151 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1152 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1153 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001154 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301155 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1156 "currentIntfId": onuDiscInd.GetIntfId()})
1157 // TODO:: Should we need to ignore raising OnuLosClear event
1158 // when onu connected to different PON?
1159 }
1160 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1161 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1162 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001163 go func() {
1164 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1165 logger.Debugw(ctx, "indication-failed", log.Fields{"error": err})
1166 }
1167 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301168 }
1169 return true
1170 })
1171
Neha Sharma96b7bf22020-06-15 10:37:32 +00001172 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001174 }
1175
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001176 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001177
1178 // check the ONU is already know to the OLT
1179 // NOTE the second time the ONU is discovered this should return a device
1180 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1181
1182 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001183 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 -08001184 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001185 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 -08001186 switch e.Code() {
1187 case codes.Internal:
1188 // this probably means NOT FOUND, so just create a new device
1189 onuDevice = nil
1190 case codes.DeadlineExceeded:
1191 // if the call times out, cleanup and exit
1192 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001193 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001194 }
1195 }
1196 }
1197
1198 if onuDevice == nil {
1199 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001200 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001201 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001202 ponintfid := onuDiscInd.GetIntfId()
npujarec5762e2020-01-01 14:08:48 +05301203 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001204
Neha Sharma96b7bf22020-06-15 10:37:32 +00001205 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001206
1207 if err != nil {
1208 // if we can't create an ID in resource manager,
1209 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001210 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001211 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001212 "pon-intf-id": ponintfid,
1213 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001214 }
1215
Neha Sharma8f4e4322020-08-06 10:51:53 +00001216 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001217 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001218 dh.discOnus.Delete(sn)
1219 dh.resourceMgr.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 +05301220 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001221 "pon-intf-id": ponintfid,
1222 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001223 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04001224 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano()); err != nil {
1225 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"error": err})
1226 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001227 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301228 log.Fields{"onuDevice": onuDevice,
1229 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001230 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301231 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001232 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001233
1234 // we can now use the existing ONU Id
1235 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001236 //Insert the ONU into cache to use in OnuIndication.
1237 //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 +00001238 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001239 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301240 "intfId": onuDiscInd.GetIntfId(),
1241 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001242 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001243
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301244 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301245 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001246 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301247 log.Fields{"onu": onuDev,
1248 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001249
Kent Hagermane6ff1012020-07-14 15:07:53 -04001250 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301251 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001253 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001254 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001255 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001256 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301257 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001259 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001260 }
1261 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001262}
1263
Mahir Gunyelb0046752021-02-26 13:51:05 -08001264func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001265
1266 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001267 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001268 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001269 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001270 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001271 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301272 log.Fields{"onuId": onuInd.OnuId,
1273 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301274 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001275 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001276 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301277
David K. Bainbridge794735f2020-02-11 21:01:37 -08001278 errFields := log.Fields{"device-id": dh.device.Id}
1279
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301280 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1281
Mahir Gunyele77977b2019-06-27 05:36:22 -07001282 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1283 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001285 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001286 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001287 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1288 if serialNumber != "" {
1289 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001290 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001291 } else {
1292 kwargs["onu_id"] = onuInd.OnuId
1293 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001294 errFields["onu-id"] = onuInd.OnuId
1295 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001296 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001297 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001298 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001299
David K. Bainbridge794735f2020-02-11 21:01:37 -08001300 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001301 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001302 }
1303
David K. Bainbridge794735f2020-02-11 21:01:37 -08001304 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001305 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 "previousIntfId": onuDevice.ParentPortNo,
1307 "currentIntfId": ponPort})
1308 }
1309
1310 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001311 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301312 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1313 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301314 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001315 }
1316 if !foundInCache {
1317 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1318
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301319 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 -08001320
1321 }
kesavand7cf3a052020-08-28 12:49:18 +05301322 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
1323 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().UnixNano()); err != nil {
1324 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"error": err})
1325 }
1326 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001327 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001328 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001329 }
1330 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001331}
1332
Neha Sharma96b7bf22020-06-15 10:37:32 +00001333func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001334 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 -07001335 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1336 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1337 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1338 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001339 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001340 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1341 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001342 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001343 onuInd.OperState = "down"
1344 }
1345 }
1346
David K. Bainbridge794735f2020-02-11 21:01:37 -08001347 switch onuInd.OperState {
1348 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001349 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 -07001350 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301351 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001352 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001353 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301354 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001355 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001356 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001357 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001358 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001359 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001360 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001361 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 -04001362 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301363 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001364 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001365 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301366 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001367 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001368 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001370 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001371 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001372 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001373 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001374 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001375 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001376}
1377
cuilin20187b2a8c32019-03-26 19:52:28 -07001378func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1379 if serialNum != nil {
1380 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001381 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001382 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001383}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001384func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1385 decodedStr, err := hex.DecodeString(serialNum[4:])
1386 if err != nil {
1387 return nil, err
1388 }
1389 return &oop.SerialNumber{
1390 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001391 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001392 }, nil
1393}
cuilin20187b2a8c32019-03-26 19:52:28 -07001394
1395func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001396 if len(vendorSpecific) > 3 {
1397 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1398 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1399 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1400 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1401 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1402 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1403 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1404 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1405 return tmp
1406 }
1407 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001408}
1409
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001410//UpdateFlowsBulk upates the bulk flow
1411func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301412 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001413}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001414
1415//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001416func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1417 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301418 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001419 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301420 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001421 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001422 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001423 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001424 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001425 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001426 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001427 "intf-id": parentPort,
1428 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001429 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001430 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 -08001431 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301432}
1433
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001434// SendPacketInToCore sends packet-in to core
1435// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1436// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001437func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001438 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001439 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001440 "port": logicalPort,
1441 "packet": hex.EncodeToString(packetPayload),
1442 "device-id": dh.device.Id,
1443 })
1444 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001445 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 +05301446 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001447 "source": "adapter",
1448 "destination": "core",
1449 "device-id": dh.device.Id,
1450 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001451 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001452 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001453 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001454 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001455 "packet": hex.EncodeToString(packetPayload),
1456 "device-id": dh.device.Id,
1457 })
1458 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001459 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001460}
1461
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001462// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001463func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001464 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001465
1466 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1467 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001468 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001469 }
1470
Kent Hagermane6ff1012020-07-14 15:07:53 -04001471 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001472 metrics := dh.metrics.GetSubscriberMetrics()
1473 for _, m := range pmConfigs.Metrics {
1474 metrics[m.Name].Enabled = m.Enabled
1475
1476 }
1477 }
1478}
1479
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001480//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301481func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001482 logger.Debugw(ctx, "received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001483
Girish Gowdra491a9c62021-01-06 16:43:07 -08001484 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001485 var errorsList []error
1486
Girish Gowdru0c588b22019-04-23 23:24:56 -04001487 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001488 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001489 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001490
Neha Sharma96b7bf22020-06-15 10:37:32 +00001491 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301492 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001493 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301494 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001495 if flow_utils.HasGroup(flow) {
1496 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1497 } else {
1498 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1499 }
Girish Gowdracefae192020-03-19 18:14:10 -07001500 if err != nil {
1501 errorsList = append(errorsList, err)
1502 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001503 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301504
1505 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001506 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001507 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301508 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001509 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301510 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001511 if flow_utils.HasGroup(flow) {
1512 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1513 } else {
1514 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1515 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001516 if err != nil {
1517 errorsList = append(errorsList, err)
1518 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301519 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001520 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001521
Girish Gowdracefae192020-03-19 18:14:10 -07001522 // 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 +00001523 if groups != nil {
1524 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001525 // err = dh.groupMgr.AddGroup(ctx, group)
1526 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001527 if err != nil {
1528 errorsList = append(errorsList, err)
1529 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001530 }
1531 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001532 // err = dh.groupMgr.ModifyGroup(ctx, group)
1533 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001534 if err != nil {
1535 errorsList = append(errorsList, err)
1536 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001537 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001538 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001539 // err = dh.groupMgr.DeleteGroup(ctx, group)
1540 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001541 if err != nil {
1542 errorsList = append(errorsList, err)
1543 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001544 }
1545 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001546 if len(errorsList) > 0 {
1547 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1548 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001549 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001550 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301551}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001552
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001553//DisableDevice disables the given device
1554//It marks the following for the given device:
1555//Device-Handler Admin-State : down
1556//Device Port-State: UNKNOWN
1557//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001558func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001559 /* On device disable ,admin state update has to be done prior sending request to agent since
1560 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001561 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001562 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001563 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001564 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001565 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001566 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001567 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001568 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001569 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001570 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301571
1572 dh.discOnus = sync.Map{}
1573 dh.onus = sync.Map{}
1574
Thomas Lee S85f37312020-04-03 17:06:12 +05301575 //stopping the stats collector
1576 dh.stopCollector <- true
1577
Neha Sharma96b7bf22020-06-15 10:37:32 +00001578 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001579 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301580 //Update device Admin state
1581 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001582 // 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 +00001583 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 -04001584 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001585 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001586 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001587 return nil
1588}
1589
Neha Sharma96b7bf22020-06-15 10:37:32 +00001590func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001591 // Update onu state as unreachable in onu adapter
1592 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301593 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001594 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001595 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001596 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001597 logger.Errorw(ctx, "failed-to-get-child-devices-information", log.Fields{"device-id": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001598 }
1599 if onuDevices != nil {
1600 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001601 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001602 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001603 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001604 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001605 "From Adapter": dh.openOLT.config.Topic, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001606 }
1607
1608 }
1609 }
1610
1611}
1612
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001613//ReenableDevice re-enables the olt device after disable
1614//It marks the following for the given device:
1615//Device-Handler Admin-State : up
1616//Device Port-State: ACTIVE
1617//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001618func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001619 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301620 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001621 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301622 }
1623 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001625
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001626 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001627
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001628 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1629 if err != nil {
divyadesai3af43e12020-08-18 07:10:54 +00001630 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001631 }
1632 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001633 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001634 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001635 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001636 device.OperStatus = voltha.OperStatus_ACTIVE
1637 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001638
Neha Sharma8f4e4322020-08-06 10:51:53 +00001639 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 +05301640 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001641 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001642 "connect-status": device.ConnectStatus,
1643 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001644 }
kesavand39e0aa32020-01-28 20:58:50 -05001645
Neha Sharma96b7bf22020-06-15 10:37:32 +00001646 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001647
1648 return nil
1649}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001650
npujarec5762e2020-01-01 14:08:48 +05301651func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001652 var uniID uint32
1653 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301654 for _, port := range onu.UniPorts {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001655 uniID = UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001656 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001657 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001658 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001659 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001660 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001661 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301662 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001663 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301664 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001665 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001666 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001667 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301668 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301672 }
npujarec5762e2020-01-01 14:08:48 +05301673 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1674 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001675 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301676 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001677 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001678 if err = dh.resourceMgr.DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001679 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 +00001680 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001681 if err = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID)); err != nil {
1682 logger.Debugw(ctx, "failed-to-remove-flow-for", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
1683 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001684 }
1685 return nil
1686}
1687
npujarec5762e2020-01-01 14:08:48 +05301688func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001689 nniUniID := -1
1690 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301691
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001692 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301693 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001694 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001695 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301696 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301697 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001698 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001699 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001700 logger.Debugw(ctx, "nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301701 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301702 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001703 _ = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, nniIntfID, -1, -1)
1704
Devmalya Paul495b94a2019-08-27 19:42:00 -04001705 }
npujarec5762e2020-01-01 14:08:48 +05301706 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001707 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301708 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001709
David K. Bainbridge794735f2020-02-11 21:01:37 -08001710 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001711}
1712
1713// 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 +05301714func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001715 logger.Debug(ctx, "function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001716 /* Clear the KV store data associated with the all the UNI ports
1717 This clears up flow data and also resource map data for various
1718 other pon resources like alloc_id and gemport_id
1719 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001720 go dh.cleanupDeviceResources(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001721 logger.Debug(ctx, "removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001722 // Stop the Stats collector
1723 dh.stopCollector <- true
1724 // stop the heartbeat check routine
1725 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301726 dh.lockDevice.RLock()
1727 // Stop the read indication only if it the routine is active
1728 if dh.isReadIndicationRoutineActive {
1729 dh.stopIndications <- true
1730 }
1731 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001732 //Reset the state
1733 if dh.Client != nil {
1734 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301735 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001736 }
1737 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08001738 dh.removeOnuIndicationChannels(ctx)
Girish Gowdrab1caa442020-10-19 12:24:39 -07001739 // There is no need to update the core about operation status and connection status of the OLT.
1740 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1741 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1742 // because the device does not exist in DB.
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001743 return nil
1744}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001745func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001746
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001747 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301748 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001749 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301750 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301751 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301752 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001753 _ = olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001754 "device-id": dh.device.Id,
Kent Hagermane6ff1012020-07-14 15:07:53 -04001755 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301756 }
1757 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301758 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001759 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301760 if err = dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001761 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301762 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301763 // Clear flowids for gem cache.
1764 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301765 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301766 }
1767 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301768 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301769 }
npujarec5762e2020-01-01 14:08:48 +05301770 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301771 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301772 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301773 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001774 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001775 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001776 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001777 /* Clear the flows from KV store associated with NNI port.
1778 There are mostly trap rules from NNI port (like LLDP)
1779 */
npujarec5762e2020-01-01 14:08:48 +05301780 if err := dh.clearNNIData(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001781 logger.Errorw(ctx, "failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001782 }
A R Karthick1f85b802019-10-11 05:06:05 +00001783
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001784 /* Clear the resource pool for each PON port in the background */
Kent Hagermane6ff1012020-07-14 15:07:53 -04001785 go func() {
1786 if err := dh.resourceMgr.Delete(ctx); err != nil {
1787 logger.Debug(ctx, err)
1788 }
1789 }()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001790 }
A R Karthick1f85b802019-10-11 05:06:05 +00001791
Devmalya Paul495b94a2019-08-27 19:42:00 -04001792 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301793 dh.onus.Range(func(key interface{}, value interface{}) bool {
1794 dh.onus.Delete(key)
1795 return true
1796 })
1797
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001798 /*Delete discovered ONU map for the device*/
1799 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1800 dh.discOnus.Delete(key)
1801 return true
1802 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001803}
1804
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001805//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001806func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001807 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301808 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001809 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001810 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001811 return nil
1812}
1813
David K. Bainbridge794735f2020-02-11 21:01:37 -08001814func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001815 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001816 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001817 "packet-indication": *packetIn,
1818 "device-id": dh.device.Id,
1819 "packet": hex.EncodeToString(packetIn.Pkt),
1820 })
1821 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001822 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001823 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001824 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001825 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001826 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001827 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001828 "logical-port-num": logicalPortNum,
1829 "device-id": dh.device.Id,
1830 "packet": hex.EncodeToString(packetIn.Pkt),
1831 })
1832 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001833
Neha Sharma8f4e4322020-08-06 10:51:53 +00001834 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 +05301835 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001836 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301837 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001838 "device-id": dh.device.Id,
1839 "packet": hex.EncodeToString(packetIn.Pkt),
1840 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001841 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001842
Matteo Scandolo92186242020-06-12 10:54:18 -07001843 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001844 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001845 "packet": hex.EncodeToString(packetIn.Pkt),
1846 "device-id": dh.device.Id,
1847 })
1848 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001849 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001850}
1851
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001852// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301853func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001854 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001855 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001856 "device-id": dh.device.Id,
1857 "egress-port-no": egressPortNo,
1858 "pkt-length": len(packet.Data),
1859 "packet": hex.EncodeToString(packet.Data),
1860 })
1861 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001862
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001863 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001864 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001865 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1866 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301867 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1868 // Do not packet-out lldp packets on uni port.
1869 // ONOS has no clue about uni/nni ports, it just packets out on all
1870 // available ports on the Logical Switch. It should not be interested
1871 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001872 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001873 "device-id": dh.device.Id,
1874 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301875 return nil
1876 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001877 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1878 if innerEthType == 0x8100 {
1879 // q-in-q 802.1ad or 802.1q double tagged packet.
1880 // slice out the outer tag.
1881 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001882 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001883 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001884 "packet-data": hex.EncodeToString(packet.Data),
1885 "device-id": dh.device.Id,
1886 })
1887 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001888 }
1889 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001890 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1891 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001892 uniID := UniIDFromPortNum(uint32(egressPortNo))
1893
Girish Gowdra9602eb42020-09-09 15:50:39 -07001894 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001895 if err != nil {
1896 // In this case the openolt agent will receive the gemPortID as 0.
1897 // The agent tries to retrieve the gemPortID in this case.
1898 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001899 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001900 "intf-id": intfID,
1901 "onu-id": onuID,
1902 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001903 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301904 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001905 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001906 }
1907
1908 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07001909 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001910 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001911 "egress-port-no": egressPortNo,
1912 "intf-id": intfID,
1913 "onu-id": onuID,
1914 "uni-id": uniID,
1915 "gem-port-id": gemPortID,
1916 "packet": hex.EncodeToString(packet.Data),
1917 "device-id": dh.device.Id,
1918 })
1919 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001920
npujarec5762e2020-01-01 14:08:48 +05301921 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301922 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001923 "source": "adapter",
1924 "destination": "onu",
1925 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001926 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001927 "oni-id": onuID,
1928 "uni-id": uniID,
1929 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001930 "packet": hex.EncodeToString(packet.Data),
1931 "device-id": dh.device.Id,
1932 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001933 }
1934 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001935 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001936 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001937 return olterrors.NewErrInvalidValue(log.Fields{
1938 "egress-nni-port": egressPortNo,
1939 "device-id": dh.device.Id,
1940 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001941 }
1942 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001943
Matteo Scandolo92186242020-06-12 10:54:18 -07001944 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001945 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001946 "uplink-pkt": uplinkPkt,
1947 "packet": hex.EncodeToString(packet.Data),
1948 "device-id": dh.device.Id,
1949 })
1950 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001951
npujarec5762e2020-01-01 14:08:48 +05301952 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001953 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1954 "packet": hex.EncodeToString(packet.Data),
1955 "device-id": dh.device.Id,
1956 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001957 }
1958 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001959 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301960 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001961 "egressPortType": egressPortType,
1962 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301963 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001964 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001965 }
1966 return nil
1967}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001968
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001969func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1970 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001971}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301972
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001973func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001974
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301975 // start the heartbeat check towards the OLT.
1976 var timerCheck *time.Timer
1977
1978 for {
1979 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1980 select {
1981 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00001982 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001983 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001984 logger.Warnw(ctx, "hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301985 if timerCheck == nil {
1986 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001987 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301988 }
1989 } else {
1990 if timerCheck != nil {
1991 if timerCheck.Stop() {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001992 logger.Debugw(ctx, "got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301993 }
1994 timerCheck = nil
1995 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001996 logger.Debugw(ctx, "hearbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05301997 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301998 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301999 }
2000 cancel()
2001 case <-dh.stopHeartbeatCheck:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002002 logger.Debugw(ctx, "stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302003 return
2004 }
2005 }
2006}
2007
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002008func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
2009 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
2010 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002011 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2012 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2013 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2014 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2015 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002016 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002017 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2018 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002019 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302020
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002021 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
2022 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002023 _ = 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 -04002024 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002025 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002026 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002027 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002028
2029 //raise olt communication failure event
2030 raisedTs := time.Now().UnixNano()
2031 device.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2032 device.OperStatus = voltha.OperStatus_UNKNOWN
2033 go dh.eventMgr.oltCommunicationEvent(ctx, device, raisedTs)
2034
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002035 go dh.cleanupDeviceResources(ctx)
2036
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002037 dh.lockDevice.RLock()
2038 // Stop the read indication only if it the routine is active
2039 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2040 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2041 // on next execution of the readIndication routine.
2042 if dh.isReadIndicationRoutineActive {
2043 dh.stopIndications <- true
2044 }
2045 dh.lockDevice.RUnlock()
2046
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002047 dh.transitionMap.Handle(ctx, DeviceInit)
2048
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302049 }
2050}
kesavand39e0aa32020-01-28 20:58:50 -05002051
2052// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002053func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2054 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2055 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002056}
2057
2058// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002059func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2060 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2061 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002062}
2063
kdarapu1afeceb2020-02-12 01:38:09 -05002064//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 +00002065func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2066 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002067 if port.GetType() == voltha.Port_ETHERNET_NNI {
2068 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002069 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302070 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302071 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002072 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002073 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002074 }
2075 // fetch interfaceid from PortNo
2076 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2077 ponIntf := &oop.Interface{IntfId: ponID}
2078 var operStatus voltha.OperStatus_Types
2079 if enablePort {
2080 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302081 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002082
2083 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302084 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002085 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002086 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002087 }
2088 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002089 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002090 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002091 } else {
2092 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302093 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002094 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302095 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002096 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002097 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002098 }
2099 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002100 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002101 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002102 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302103 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 +05302104 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302105 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002106 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002107 }
2108 return nil
2109}
2110
kdarapu1afeceb2020-02-12 01:38:09 -05002111//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002112func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002113 // Disable the port and update the oper_port_status to core
2114 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002115 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002116 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002117 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302118 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302119 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002120 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002121 }
2122 }
2123 }
2124 return nil
2125}
2126
2127//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002128func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2129 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2130 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002131 if port.Type == voltha.Port_ETHERNET_NNI {
2132 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002133 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002134 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002135 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002136 }
2137 }
2138 if port.Type == voltha.Port_PON_OLT {
2139 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002140 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002141 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002142 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002143 }
2144 }
2145 }
2146}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002147
2148// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002149func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002150 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002151 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2152 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002153
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002154 var sn *oop.SerialNumber
2155 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002156 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302157 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002158 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302159 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002160 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002161 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002162
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002163 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Neha Sharma8f4e4322020-08-06 10:51:53 +00002164 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302165 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302166 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002167 "onu-id": onuID}, err).Log()
2168 }
2169 //clear PON resources associated with ONU
2170 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002171 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002172 logger.Warnw(ctx, "failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002173 "device-id": dh.device.Id,
2174 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002175 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002176 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002177 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002178 "device-id": dh.device.Id,
2179 "intf-id": intfID,
2180 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002181 } else {
2182 for i, onu := range onuGemData {
Girish Gowdraa0870562021-03-11 14:30:14 -08002183 if onu.OnuID == onuID && onu.SerialNumber == onuSn {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002185 if err := dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002186 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302187 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002188 "onu-device": onu,
2189 "error": err})
2190 }
2191 // Clear flowids for gem cache.
2192 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002193 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002194 }
2195 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002196 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002197 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002198 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002199 "intf-id": intfID,
2200 "onu-device": onu,
2201 "onu-gem": onuGemData,
2202 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002203 //Not returning error on cleanup.
2204 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002205 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002206 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002207 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002208 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002209 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002210 }
2211 }
2212 dh.onus.Delete(onuKey)
Girish Gowdraa0870562021-03-11 14:30:14 -08002213 dh.discOnus.Delete(onuSn)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002214 return nil
2215}
Girish Gowdracefae192020-03-19 18:14:10 -07002216
2217func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002218 for _, field := range flow_utils.GetOfbFields(flow) {
2219 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002220 return field.GetPort()
2221 }
2222 }
2223 return InvalidPort
2224}
2225
2226func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002227 for _, action := range flow_utils.GetActions(flow) {
2228 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002229 if out := action.GetOutput(); out != nil {
2230 return out.GetPort()
2231 }
2232 }
2233 }
2234 return InvalidPort
2235}
2236
Girish Gowdracefae192020-03-19 18:14:10 -07002237func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2238 inPort := getInPortFromFlow(flow)
2239 outPort := getOutPortFromFlow(flow)
2240
2241 if inPort == InvalidPort || outPort == InvalidPort {
2242 return inPort, outPort
2243 }
2244
2245 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2246 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2247 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002248 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002249 return uniPort, outPort
2250 }
2251 }
2252 } else {
2253 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2254 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002255 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002256 return inPort, uniPort
2257 }
2258 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2259 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002260 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002261 return uniPort, outPort
2262 }
2263 }
2264 }
2265
2266 return InvalidPort, InvalidPort
2267}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002268
2269func extractOmciTransactionID(omciPkt []byte) uint16 {
2270 if len(omciPkt) > 3 {
2271 d := omciPkt[0:2]
2272 transid := binary.BigEndian.Uint16(d)
2273 return transid
2274 }
2275 return 0
2276}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002277
2278// StoreOnuDevice stores the onu parameters to the local cache.
2279func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2280 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2281 dh.onus.Store(onuKey, onuDevice)
2282}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002283
Neha Sharma8f4e4322020-08-06 10:51:53 +00002284func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002285 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002286 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002287 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002288 resp := new(voltha.ReturnValues)
2289 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002290 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002291 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002292 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2293 return nil, err
2294 }
2295 ID = device.ProxyAddress.GetOnuId()
2296 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2297 valueparam.Onu = &Onu
2298 valueparam.Value = value
2299
2300 // This API is unsupported until agent patch is added
2301 resp.Unsupported = uint32(value)
2302 _ = ctx
2303
2304 // Uncomment this code once agent changes are complete and tests
2305 /*
2306 resp, err = dh.Client.GetValue(ctx, valueparam)
2307 if err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002308 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002309 return nil, err
2310 }
2311 */
2312
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002313 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 -08002314 return resp, nil
2315}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002316
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002317func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002318 // Default to PON0
2319 var intfID uint32
2320 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002321 if inPort != InvalidPort && outPort != InvalidPort {
2322 _, intfID, _, _ = ExtractAccessFromFlow(inPort, outPort)
2323 }
2324 return intfID
2325}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002326
Mahir Gunyelb0046752021-02-26 13:51:05 -08002327func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2328 dh.perPonOnuIndicationChannelLock.Lock()
2329 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2330 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002331 return ch.indicationChannel
2332 }
2333 channels := onuIndicationChannels{
2334 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002335 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002336 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002337 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002338 stopChannel: make(chan struct{}),
2339 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002340 dh.perPonOnuIndicationChannel[intfID] = channels
2341 dh.perPonOnuIndicationChannelLock.Unlock()
2342 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002343 return channels.indicationChannel
2344
2345}
2346
Mahir Gunyelb0046752021-02-26 13:51:05 -08002347func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2348 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2349 dh.perPonOnuIndicationChannelLock.Lock()
2350 defer dh.perPonOnuIndicationChannelLock.Unlock()
2351 for _, v := range dh.perPonOnuIndicationChannel {
2352 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002353 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002354 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002355}
2356
Mahir Gunyelb0046752021-02-26 13:51:05 -08002357func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2358 ind := onuIndicationMsg{
2359 ctx: ctx,
2360 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002361 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002362 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002363 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002364 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002365}
2366
Mahir Gunyelb0046752021-02-26 13:51:05 -08002367func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002368 for {
2369 select {
2370 // process one indication per onu, before proceeding to the next one
2371 case onuInd := <-onuChannels.indicationChannel:
2372 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Mahir Gunyelb0046752021-02-26 13:51:05 -08002373 "ind": onuInd.indication})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002374 switch onuInd.indication.Data.(type) {
2375 case *oop.Indication_OnuInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002376 if err := dh.onuIndication(onuInd.ctx, onuInd.indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002377 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2378 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002379 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002380 }
2381 case *oop.Indication_OnuDiscInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002382 if err := dh.onuDiscIndication(onuInd.ctx, onuInd.indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002383 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2384 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002385 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002386 }
2387 }
2388 case <-onuChannels.stopChannel:
2389 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2390 close(onuChannels.indicationChannel)
2391 return
2392 }
2393 }
2394}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002395
2396// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2397// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
2398func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *voltha.OfpFlowStats, group *voltha.OfpGroupEntry, action string) error {
2399 // Step1 : Fill McastFlowOrGroupControlBlock
2400 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2401 // Step3 : Wait on response channel for response
2402 // Step4 : Return error value
2403 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2404 errChan := make(chan error)
2405 var groupID uint32
2406 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2407 ctx: ctx,
2408 flowOrGroupAction: action,
2409 flow: flow,
2410 group: group,
2411 errChan: &errChan,
2412 }
2413 if flow != nil {
2414 groupID = flow_utils.GetGroup(flow)
2415 } else if group != nil {
2416 groupID = group.Desc.GroupId
2417 } else {
2418 return errors.New("flow-and-group-both-nil")
2419 }
2420 // Derive the appropriate go routine to handle the request by a simple module operation.
2421 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2422 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2423 // Wait for handler to return error value
2424 err := <-errChan
2425 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"flow": flow, "group": group, "action": action, "err": err})
2426 return err
2427}
2428
2429// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
2430func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock) {
2431 for {
2432 // block on the channel to receive an incoming mcast flow/group
2433 // process the flow completely before proceeding to handle the next flow
2434 mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel
2435 if mcastFlowOrGroupCb.flow != nil {
2436 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2437 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2438 log.Fields{"device-id": dh.device.Id,
2439 "flowToAdd": mcastFlowOrGroupCb.flow})
2440 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2441 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2442 // Pass the return value over the return channel
2443 *mcastFlowOrGroupCb.errChan <- err
2444 } else { // flow remove
2445 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2446 log.Fields{"device-id": dh.device.Id,
2447 "flowToRemove": mcastFlowOrGroupCb.flow})
2448 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2449 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2450 // Pass the return value over the return channel
2451 *mcastFlowOrGroupCb.errChan <- err
2452 }
2453 } else { // mcast group
2454 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2455 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2456 log.Fields{"device-id": dh.device.Id,
2457 "groupToAdd": mcastFlowOrGroupCb.group})
2458 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2459 // Pass the return value over the return channel
2460 *mcastFlowOrGroupCb.errChan <- err
2461 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2462 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2463 log.Fields{"device-id": dh.device.Id,
2464 "groupToModify": mcastFlowOrGroupCb.group})
2465 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2466 // Pass the return value over the return channel
2467 *mcastFlowOrGroupCb.errChan <- err
2468 } else { // group remove
2469 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2470 log.Fields{"device-id": dh.device.Id,
2471 "groupToRemove": mcastFlowOrGroupCb.group})
2472 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2473 // Pass the return value over the return channel
2474 *mcastFlowOrGroupCb.errChan <- err
2475 }
2476 }
2477 }
2478}
kesavand62126212021-01-12 04:56:06 -05002479
2480func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2481
2482 singleValResp := extension.SingleGetValueResponse{
2483 Response: &extension.GetValueResponse{
2484 Response: &extension.GetValueResponse_PortCoutners{
2485 PortCoutners: &extension.GetOltPortCountersResponse{},
2486 },
2487 },
2488 }
2489
2490 errResp := func(status extension.GetValueResponse_Status,
2491 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2492 return &extension.SingleGetValueResponse{
2493 Response: &extension.GetValueResponse{
2494 Status: status,
2495 ErrReason: reason,
2496 },
2497 }
2498 }
2499
2500 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2501 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2502 //send error response
2503 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2504 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2505 }
2506 statIndChn := make(chan bool, 1)
2507 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2508 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2509 //request openOlt agent to send the the port statistics indication
2510
2511 go func() {
2512 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2513 if err != nil {
2514 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2515 }
2516 }()
2517 select {
2518 case <-statIndChn:
2519 //indication received for ports stats
2520 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2521 case <-time.After(oltPortInfoTimeout * time.Second):
2522 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2523 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2524 case <-ctx.Done():
2525 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2526 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2527 }
2528 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2529 //get nni stats
2530 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
2531 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2532 cmnni := dh.portStats.collectNNIMetrics(intfID)
2533 if cmnni == nil {
2534 //TODO define the error reason
2535 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2536 }
2537 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2538 return &singleValResp
2539
2540 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2541 // get pon stats
2542 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
2543 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2544 cmpon := dh.portStats.collectPONMetrics(intfID)
2545 if cmpon == nil {
2546 //TODO define the error reason
2547 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2548 }
2549 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2550 return &singleValResp
2551 }
2552 }
2553 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2554}