blob: fdb08592a86436171f7554fc95e6b617e93a25b5 [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
Gamze Abakac2c32a62021-03-11 11:44:18 +0000104
105 adapterPreviouslyConnected bool
106 agentPreviouslyConnected bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107}
108
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700112 deviceType string
113 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 onuID uint32
115 intfID uint32
116 proxyDeviceID string
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530117 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400118 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700119}
120
Mahir Gunyelb0046752021-02-26 13:51:05 -0800121type onuIndicationMsg struct {
122 ctx context.Context
123 indication *oop.Indication
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800124}
125
126type onuIndicationChannels struct {
Mahir Gunyelb0046752021-02-26 13:51:05 -0800127 indicationChannel chan onuIndicationMsg
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800128 stopChannel chan struct{}
129}
130
Girish Gowdra491a9c62021-01-06 16:43:07 -0800131//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
132//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
133//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
134//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
135type McastFlowOrGroupControlBlock struct {
136 ctx context.Context // Flow/group handler context
137 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
138 flow *voltha.OfpFlowStats // Flow message (can be nil or valid flow)
139 group *voltha.OfpGroupEntry // Group message (can be nil or valid group)
140 errChan *chan error // channel to report the mcast Flow/group handling error
141}
142
Naga Manjunath7615e552019-10-11 22:35:47 +0530143var pmNames = []string{
144 "rx_bytes",
145 "rx_packets",
146 "rx_mcast_packets",
147 "rx_bcast_packets",
148 "tx_bytes",
149 "tx_packets",
150 "tx_mcast_packets",
151 "tx_bcast_packets",
152}
153
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700154//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530155func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700156 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700157 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700158 device.deviceType = deviceTp
159 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700160 device.onuID = onuID
161 device.intfID = intfID
162 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530163 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700164 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530165}
166
167//NewDeviceHandler creates a new device handler
Himani Chawlacd407802020-12-10 12:08:59 +0530168func 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 -0700169 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800170 dh.cm = cm
cuilin20187b2a8c32019-03-26 19:52:28 -0700171 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400172 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400173 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700174 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700175 dh.device = cloned
176 dh.openOLT = adapter
177 dh.exitChannel = make(chan int, 1)
178 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530179 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530180 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530181 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 -0500182 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400183 dh.stopIndications = make(chan bool, 1)
Mahir Gunyelb0046752021-02-26 13:51:05 -0800184 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800185 // Create a slice of buffered channels for handling concurrent mcast flow/group.
186 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
187 for i := range dh.incomingMcastFlowOrGroup {
188 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
189 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
190 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
191 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
192 // for incoming mcast flow/group to be processed serially.
193 go dh.mcastFlowOrGroupChannelHandlerRoutine(dh.incomingMcastFlowOrGroup[i])
194 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700195 //TODO initialize the support classes.
196 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530197}
198
199// start save the device to the data model
200func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700201 dh.lockDevice.Lock()
202 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000203 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700204 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000205 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530206}
207
208// stop stops the device dh. Not much to do for now
209func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700210 dh.lockDevice.Lock()
211 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000212 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700213 dh.exitChannel <- 1
Neha Sharma96b7bf22020-06-15 10:37:32 +0000214 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530215}
216
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400217func macifyIP(ip net.IP) string {
218 if len(ip) > 0 {
219 oct1 := strconv.FormatInt(int64(ip[12]), 16)
220 oct2 := strconv.FormatInt(int64(ip[13]), 16)
221 oct3 := strconv.FormatInt(int64(ip[14]), 16)
222 oct4 := strconv.FormatInt(int64(ip[15]), 16)
223 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
224 }
225 return ""
226}
227
Neha Sharma96b7bf22020-06-15 10:37:32 +0000228func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400229 var genmac string
230 var addr net.IP
231 var ips []string
232 var err error
233
Neha Sharma96b7bf22020-06-15 10:37:32 +0000234 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400235
236 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000237 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400238
239 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000240 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400241 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000242 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400243 }
244 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000245 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530246 log.Fields{"host": ips[0],
247 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400248 return genmac, nil
249 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000250 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400251 }
252
253 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000254 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530255 log.Fields{"host": host,
256 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400257 return genmac, nil
258}
259
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530260func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700261 slist := strings.Split(mac, ":")
262 result := make([]uint32, len(slist))
263 var err error
264 var tmp int64
265 for index, val := range slist {
266 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
267 return []uint32{1, 2, 3, 4, 5, 6}
268 }
269 result[index] = uint32(tmp)
270 }
271 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530272}
273
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700274//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 -0800275func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530276
David K. Bainbridge794735f2020-02-11 21:01:37 -0800277 switch portType {
278 case voltha.Port_ETHERNET_NNI:
279 return fmt.Sprintf("nni-%d", portNum), nil
280 case voltha.Port_PON_OLT:
281 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700282 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800283
Girish Kumarf26e4882020-03-05 06:49:10 +0000284 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530285}
286
Neha Sharma96b7bf22020-06-15 10:37:32 +0000287func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000288 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700289 if state == "up" {
290 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500291 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500292 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700293 } else {
294 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500295 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700296 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700297 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400298 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800299 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000300 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400301 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500302
Neha Sharma8f4e4322020-08-06 10:51:53 +0000303 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 +0000304 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
Neha Sharma8f4e4322020-08-06 10:51:53 +0000305 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 -0400306 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
307 "device-id": dh.device.Id,
308 "port-type": portType,
309 "port-number": portNum,
310 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500311 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400312 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500313 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400314 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700315 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400316 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700317 PortNo: portNum,
318 Label: label,
319 Type: portType,
320 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700321 OfpPort: &of.OfpPort{
322 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
323 Config: 0,
324 State: uint32(of.OfpPortState_OFPPS_LIVE),
325 Curr: capacity,
326 Advertised: capacity,
327 Peer: capacity,
328 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
329 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
330 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700331 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000332 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700333 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000334 if err := dh.coreProxy.PortCreated(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000335 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800336 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000337 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400338 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000339 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530340 return nil
341}
342
Kent Hagermane6ff1012020-07-14 15:07:53 -0400343func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +0000344 device, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530345 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400346 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
347 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530348 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800349 dh.lockDevice.Lock()
350 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530351 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530352}
353
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700354// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530355// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800356func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000357 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700358 defer func() {
359 dh.lockDevice.Lock()
360 dh.isReadIndicationRoutineActive = false
361 dh.lockDevice.Unlock()
362 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700363 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700364 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700365 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700366 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400367 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530368 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400369 if err != nil || device == nil {
370 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000371 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400372 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400373
David Bainbridgef5879ca2019-12-13 21:17:54 +0000374 // Create an exponential backoff around re-enabling indications. The
375 // maximum elapsed time for the back off is set to 0 so that we will
376 // continue to retry. The max interval defaults to 1m, but is set
377 // here for code clarity
378 indicationBackoff := backoff.NewExponentialBackOff()
379 indicationBackoff.MaxElapsedTime = 0
380 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700381
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700382 dh.lockDevice.Lock()
383 dh.isReadIndicationRoutineActive = true
384 dh.lockDevice.Unlock()
385
Girish Gowdra3f974912020-03-23 20:35:18 -0700386Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700387 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400388 select {
389 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000390 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700391 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400392 default:
393 indication, err := indications.Recv()
394 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000395 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530396 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530397 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400398 // Use an exponential back off to prevent getting into a tight loop
399 duration := indicationBackoff.NextBackOff()
400 if duration == backoff.Stop {
401 // If we reach a maximum then warn and reset the backoff
402 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000403 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530404 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530405 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400406 indicationBackoff.Reset()
407 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700408
409 // On failure process a backoff timer while watching for stopIndications
410 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700411 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700412 select {
413 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000414 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700415 if !backoffTimer.Stop() {
416 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700417 }
418 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700419 case <-backoffTimer.C:
420 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700421 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700422 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
423 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400424 }
425 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000426 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530427 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000428 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530429 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530430 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700431 // Close the stream, and re-initialize it
432 if err = indications.CloseSend(); err != nil {
433 // Ok to ignore here, because we landed here due to a problem on the stream
434 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000435 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530436 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530437 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700438 }
439 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
440 return err
441 }
442 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400443 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530444 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400445 // Reset backoff if we have a successful receive
446 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400447 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530448 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000449 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530450 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530451 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400452 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400453 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400454 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700455 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700456 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700457 // Close the send stream
458 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700459
Girish Gowdra3f974912020-03-23 20:35:18 -0700460 return nil
461}
462
463func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
464
465 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
466 if err != nil {
467 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
468 }
469 if indications == nil {
470 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
471 }
472
473 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400474}
475
476// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
477func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
478 switch indication.Data.(type) {
479 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
480 return true
481
482 default:
483 return false
484 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700485}
486
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700488 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000489 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530490 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700491 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530492 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700493 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000494 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000495 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530496 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000497 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800498 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000499 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800500 }
501 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700502}
503
David K. Bainbridge794735f2020-02-11 21:01:37 -0800504// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530505func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700506 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700507 switch indication.Data.(type) {
508 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000509 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
510 defer span.Finish()
511
David K. Bainbridge794735f2020-02-11 21:01:37 -0800512 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400513 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800514 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700515 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000516 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
517 defer span.Finish()
518
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700519 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800520 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000521 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400522 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800523 }
524 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000525 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700526 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000527 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
528 defer span.Finish()
529
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700530 intfOperInd := indication.GetIntfOperInd()
531 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800532 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000533 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400534 _ = 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 -0800535 }
536 }()
Kent Hagermane6ff1012020-07-14 15:07:53 -0400537 if err := dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId()); err != nil {
538 logger.Warn(ctx, err)
539 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700540 } else if intfOperInd.GetType() == "pon" {
541 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
542 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800543 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000544 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400545 _ = 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 -0800546 }
547 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000548 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700549 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000550 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530551 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530552 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700553 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000554 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
555 defer span.Finish()
556
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700557 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000558 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800559 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800560 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700561 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000562 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
563 defer span.Finish()
564
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700565 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000566 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800567 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800568 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700569 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000570 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
571 defer span.Finish()
572
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700573 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000574 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 -0800575 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000576 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400577 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800578 }
579 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700580 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000581 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
582 defer span.Finish()
583
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700584 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000585 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700586 "intf-type": pktInd.IntfId,
587 "intf-id": pktInd.IntfId,
588 "gem-port-id": pktInd.GemportId,
589 "port-no": pktInd.PortNo,
590 "device-id": dh.device.Id,
591 })
592
593 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000594 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700595 "intf-type": pktInd.IntfId,
596 "intf-id": pktInd.IntfId,
597 "gem-port-id": pktInd.GemportId,
598 "port-no": pktInd.PortNo,
599 "packet": hex.EncodeToString(pktInd.Pkt),
600 "device-id": dh.device.Id,
601 })
602 }
603
David K. Bainbridge794735f2020-02-11 21:01:37 -0800604 go func() {
605 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400606 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800607 }
608 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000610 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
611 defer span.Finish()
612
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700613 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700614 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700615 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000616 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
617 defer span.Finish()
618
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700619 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000620 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700621 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000622 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
623 defer span.Finish()
624
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700625 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000626 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
627 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700628 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530629}
630
631// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530632func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530633 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000634 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530635
Girish Gowdru0c588b22019-04-23 23:24:56 -0400636 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530637 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400638 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000639 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400640 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000641
642 //Clear olt communication failure event
643 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
644 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700645 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000646 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
647
Gamze Abakac2c32a62021-03-11 11:44:18 +0000648 //check adapter and agent reconcile status
649 //reboot olt if needed (olt disconnection case)
650 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
651 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
652 log.Fields{
653 "device-id": dh.device.Id,
654 "adapter-status": dh.adapterPreviouslyConnected,
655 "agent-status": dh.agentPreviouslyConnected,
656 })
657 _ = dh.RebootDevice(ctx, dh.device)
658 }
659
Girish Gowdru0c588b22019-04-23 23:24:56 -0400660 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530661}
662
663// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530664func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000665 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400666
npujarec5762e2020-01-01 14:08:48 +0530667 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400668 if err != nil || device == nil {
669 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000670 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400671 }
672
673 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400674
675 //Update the device oper state and connection status
676 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800677 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400678 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800679 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400680
David K. Bainbridge794735f2020-02-11 21:01:37 -0800681 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000682 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400683 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400684
685 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530686 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400687 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000688 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400689 }
690 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400691 // Update onu state as down in onu adapter
692 onuInd := oop.OnuIndication{}
693 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800694 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +0300695 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800696 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400697 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +0300698 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800699 "onu-indicator": onuInd,
700 "device-type": onuDevice.Type,
701 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700702 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800703 } else {
704 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 -0700705 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400706 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800707 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700708 /* Discovered ONUs entries need to be cleared , since after OLT
709 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530710 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800711 dh.lockDevice.Unlock()
712
Neha Sharma96b7bf22020-06-15 10:37:32 +0000713 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700714 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530715}
716
717// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530718func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400719 var err error
Girish Kumar93e91742020-07-27 16:43:19 +0000720 // Use Intercepters to automatically inject and publish Open Tracing Spans by this GRPC client
721 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
722 grpc.WithInsecure(),
723 grpc.WithBlock(),
724 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000725 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000726 )),
727 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000728 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000729 )))
730
731 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530732 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530733 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000734 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400735 }
736 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530737}
738
739// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530740func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400741 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530742 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400743 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530744}
745
746// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530747func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530748 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000749 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400750
751 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530752 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
753 if err != nil || device == nil {
754 /*TODO: needs to handle error scenarios */
755 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
756 }
757 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000758 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400759
760 cloned := proto.Clone(device).(*voltha.Device)
761 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
762 cloned.OperStatus = voltha.OperStatus_UNKNOWN
763 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530764 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
765 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 -0400766 }
767
Chaitrashree G S44124192019-08-07 20:21:36 -0400768 // 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 +0530769 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400770 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530771 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400772 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400773 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
774 // all the modules initialized and ready to handle incoming ONUs.
775
Thomas Lee S985938d2020-05-04 11:40:41 +0530776 err = dh.initializeDeviceHandlerModules(ctx)
777 if err != nil {
778 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 -0400779 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400780
781 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800782 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530783 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400784 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800785 }
786 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700787
788 go startHeartbeatCheck(ctx, dh)
789
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400790 return nil
791 }
792
Neha Sharma8f4e4322020-08-06 10:51:53 +0000793 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400794 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400795 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400796 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400797 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400798 dh.populateActivePorts(ctx, ports)
799 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
800 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400801 }
802
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400803 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530804 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 -0400805 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530806
cuilin20187b2a8c32019-03-26 19:52:28 -0700807 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800808 go func() {
809 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400810 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800811 }
812 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000813 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000814
815 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000816 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000817 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700818
819 go startHeartbeatCheck(ctx, dh)
820
cuilin20187b2a8c32019-03-26 19:52:28 -0700821 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530822}
823
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400824func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000825 deviceInfo, err := dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400826
827 if err != nil {
828 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
829 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700830 dh.totalPonPorts = deviceInfo.GetPonPorts()
Gamze Abakac2c32a62021-03-11 11:44:18 +0000831 dh.agentPreviouslyConnected = deviceInfo.PreviouslyConnected
Girish Gowdra9602eb42020-09-09 15:50:39 -0700832
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400833 // Instantiate resource manager
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800834 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 -0400835 return olterrors.ErrResourceManagerInstantiating
836 }
837
Girish Gowdra9602eb42020-09-09 15:50:39 -0700838 dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400839
Girish Gowdra9602eb42020-09-09 15:50:39 -0700840 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
841 for i := range dh.flowMgr {
842 // Instantiate flow manager
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700843 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr, dh.groupMgr, uint32(i)); dh.flowMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700844 return olterrors.ErrResourceManagerInstantiating
845 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400846 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700847
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400848 /* TODO: Instantiate Alarm , stats , BW managers */
849 /* Instantiating Event Manager to handle Alarms and KPIs */
850 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
851
852 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000853 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400854
855 return nil
856
857}
858
Neha Sharma96b7bf22020-06-15 10:37:32 +0000859func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400860 var err error
861 var deviceInfo *oop.DeviceInfo
862
Neha Sharma8f4e4322020-08-06 10:51:53 +0000863 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400864
865 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000866 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400867 }
868 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000869 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400870 }
871
Neha Sharma96b7bf22020-06-15 10:37:32 +0000872 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400873 dh.device.Root = true
874 dh.device.Vendor = deviceInfo.Vendor
875 dh.device.Model = deviceInfo.Model
876 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
877 dh.device.HardwareVersion = deviceInfo.HardwareVersion
878 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
879
880 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000881 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400882 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000883 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400884 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000885 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400886 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000887 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400888 dh.device.MacAddress = genmac
889 } else {
890 dh.device.MacAddress = deviceInfo.DeviceId
891 }
892
893 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000894 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000895 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400896 }
897
898 return deviceInfo, nil
899}
900
Neha Sharma96b7bf22020-06-15 10:37:32 +0000901func startCollector(ctx context.Context, dh *DeviceHandler) {
902 logger.Debugf(ctx, "starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530903 for {
904 select {
905 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000906 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530907 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000908 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700909
Neha Sharma8f4e4322020-08-06 10:51:53 +0000910 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400911 if err != nil {
912 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
913 continue
914 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530915 for _, port := range ports {
916 // NNI Stats
917 if port.Type == voltha.Port_ETHERNET_NNI {
918 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
919 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000920 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000921 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000922 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530923 }
924 // PON Stats
925 if port.Type == voltha.Port_PON_OLT {
926 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
927 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
928 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000929 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000930 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530931 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000932 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000933
934 //ONU & Gem Stats
935 onuGemInfo := dh.flowMgr[intfID].onuGemInfo
936 if len(onuGemInfo) != 0 {
937 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfo)
938 }
Chaitrashree G Sef088112020-02-03 21:39:27 -0500939 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530940 }
941 }
942 }
943}
944
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700945//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530946func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400947 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000948 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530949 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530950
951 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400952 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
953 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530954 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530955}
956
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700957//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530958func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700959 return &ic.SwitchCapability{
960 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530961 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700962 HwDesc: "open_pon",
963 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700964 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -0700965 },
966 SwitchFeatures: &of.OfpSwitchFeatures{
967 NBuffers: 256,
968 NTables: 2,
969 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
970 of.OfpCapabilities_OFPC_TABLE_STATS |
971 of.OfpCapabilities_OFPC_PORT_STATS |
972 of.OfpCapabilities_OFPC_GROUP_STATS),
973 },
974 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530975}
976
Neha Sharma96b7bf22020-06-15 10:37:32 +0000977func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
978 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 -0700979 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700980 var deviceID string
981 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700982
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400983 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700984 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000985 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 -0700986 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
987 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400988
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700989 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530990
991 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
992
Neha Sharma96b7bf22020-06-15 10:37:32 +0000993 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 -0700994 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700995 kwargs := make(map[string]interface{})
996 kwargs["onu_id"] = omciInd.OnuId
997 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700998
Neha Sharma8f4e4322020-08-06 10:51:53 +0000999 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001000 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301001 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001002 "intf-id": omciInd.IntfId,
1003 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001004 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005 deviceType = onuDevice.Type
1006 deviceID = onuDevice.Id
1007 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
1008 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301009 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001010 } else {
1011 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001012 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 +05301013 deviceType = onuInCache.(*OnuDevice).deviceType
1014 deviceID = onuInCache.(*OnuDevice).deviceID
1015 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -07001016 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001017
1018 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +00001019 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001020 ic.InterAdapterMessageType_OMCI_REQUEST, dh.openOLT.config.Topic, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001021 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301022 return olterrors.NewErrCommunication("omci-request", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001023 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001024 "destination": deviceType,
1025 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001026 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001027 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301029}
1030
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001031//ProcessInterAdapterMessage sends the proxied messages to the target device
1032// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1033// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001034func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
1035 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001036 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001037 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -07001038 fromTopic := msg.Header.FromTopic
1039 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001040 toDeviceID := msg.Header.ToDeviceId
1041 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -07001042
Neha Sharma96b7bf22020-06-15 10:37:32 +00001043 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 -07001044
1045 msgBody := msg.GetBody()
1046
1047 omciMsg := &ic.InterAdapterOmciMessage{}
1048 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001049 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001050 }
1051
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001052 if omciMsg.GetProxyAddress() == nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001053 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001054 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301055 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001056 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001057 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001058 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001059 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1060 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301061 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001062 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001063 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001064 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001065 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001066 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1067 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301068 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001069 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001070 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001072 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001073 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001074 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001075 }
1076 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301077}
1078
Neha Sharma96b7bf22020-06-15 10:37:32 +00001079func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001080 var intfID uint32
1081 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001082 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001083 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084 intfID = onuDevice.ProxyAddress.GetChannelId()
1085 onuID = onuDevice.ProxyAddress.GetOnuId()
1086 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001087 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001088 intfID = omciMsg.GetProxyAddress().GetChannelId()
1089 onuID = omciMsg.GetProxyAddress().GetOnuId()
1090 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001091 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001092 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001093 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 -08001094
Thomas Lee S94109f12020-03-03 16:39:29 +05301095 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001096 "intf-id": intfID,
1097 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001098 }
1099
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001100 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1101 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001102 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001103 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1104 hex.Encode(hexPkt, omciMsg.Message)
1105 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1106
1107 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1108 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1109 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001110 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001111 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001112
Neha Sharma8f4e4322020-08-06 10:51:53 +00001113 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001114 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301115 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001116 "intf-id": intfID,
1117 "onu-id": onuID,
1118 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001119 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001120 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001121}
1122
David K. Bainbridge794735f2020-02-11 21:01:37 -08001123func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301124 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 -07001125 if err := dh.flowMgr[intfID].UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001126 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001127 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001128 // TODO: need resource manager
1129 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301130 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301131 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001132 st, _ := status.FromError(err)
1133 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001134 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1135
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001136 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301137 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001138 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001139 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001140 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001141 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001143}
1144
Mahir Gunyelb0046752021-02-26 13:51:05 -08001145func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001146 channelID := onuDiscInd.GetIntfId()
1147 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001148
Mahir Gunyelb0046752021-02-26 13:51:05 -08001149 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001150 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301151
cuilin20187b2a8c32019-03-26 19:52:28 -07001152 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001153 if sn != "" {
1154 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001155 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001156 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001157 }
1158
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301159 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001160 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001161 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301162
1163 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1164 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1165 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1166 OnuLosRaise event sent for it */
1167 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1168 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1169 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001170 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301171 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1172 "currentIntfId": onuDiscInd.GetIntfId()})
1173 // TODO:: Should we need to ignore raising OnuLosClear event
1174 // when onu connected to different PON?
1175 }
1176 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1177 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1178 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001179 go func() {
1180 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1181 logger.Debugw(ctx, "indication-failed", log.Fields{"error": err})
1182 }
1183 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301184 }
1185 return true
1186 })
1187
Neha Sharma96b7bf22020-06-15 10:37:32 +00001188 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001189 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001190 }
1191
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001192 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001193
1194 // check the ONU is already know to the OLT
1195 // NOTE the second time the ONU is discovered this should return a device
1196 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1197
1198 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001199 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 -08001200 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001201 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 -08001202 switch e.Code() {
1203 case codes.Internal:
1204 // this probably means NOT FOUND, so just create a new device
1205 onuDevice = nil
1206 case codes.DeadlineExceeded:
1207 // if the call times out, cleanup and exit
1208 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001209 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001210 }
1211 }
1212 }
1213
1214 if onuDevice == nil {
1215 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001216 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001217 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001218 ponintfid := onuDiscInd.GetIntfId()
npujarec5762e2020-01-01 14:08:48 +05301219 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001220
Neha Sharma96b7bf22020-06-15 10:37:32 +00001221 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001222
1223 if err != nil {
1224 // if we can't create an ID in resource manager,
1225 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001226 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001227 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001228 "pon-intf-id": ponintfid,
1229 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001230 }
1231
Neha Sharma8f4e4322020-08-06 10:51:53 +00001232 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001233 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001234 dh.discOnus.Delete(sn)
1235 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 +05301236 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001237 "pon-intf-id": ponintfid,
1238 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001239 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001240 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().Unix()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001241 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"error": err})
1242 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001243 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301244 log.Fields{"onuDevice": onuDevice,
1245 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001246 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301247 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001248 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001249
1250 // we can now use the existing ONU Id
1251 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001252 //Insert the ONU into cache to use in OnuIndication.
1253 //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 +00001254 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001255 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301256 "intfId": onuDiscInd.GetIntfId(),
1257 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001258 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001259
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301260 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301261 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001262 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301263 log.Fields{"onu": onuDev,
1264 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001265
Kent Hagermane6ff1012020-07-14 15:07:53 -04001266 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301267 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001268 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001269 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001270 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001271 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001272 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301273 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001275 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001276 }
1277 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001278}
1279
Mahir Gunyelb0046752021-02-26 13:51:05 -08001280func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001281
1282 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001283 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001284 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001285 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001286 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001287 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301288 log.Fields{"onuId": onuInd.OnuId,
1289 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301290 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001291 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001292 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301293
David K. Bainbridge794735f2020-02-11 21:01:37 -08001294 errFields := log.Fields{"device-id": dh.device.Id}
1295
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301296 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1297
Mahir Gunyele77977b2019-06-27 05:36:22 -07001298 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1299 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001300 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001301 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001302 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001303 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1304 if serialNumber != "" {
1305 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001307 } else {
1308 kwargs["onu_id"] = onuInd.OnuId
1309 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 errFields["onu-id"] = onuInd.OnuId
1311 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001312 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001313 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001314 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001315
David K. Bainbridge794735f2020-02-11 21:01:37 -08001316 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001317 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001318 }
1319
David K. Bainbridge794735f2020-02-11 21:01:37 -08001320 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001321 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322 "previousIntfId": onuDevice.ParentPortNo,
1323 "currentIntfId": ponPort})
1324 }
1325
1326 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001327 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301328 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1329 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301330 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001331 }
1332 if !foundInCache {
1333 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1334
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301335 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 -08001336
1337 }
kesavand7cf3a052020-08-28 12:49:18 +05301338 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001339 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
kesavand7cf3a052020-08-28 12:49:18 +05301340 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"error": err})
1341 }
1342 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001343 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001344 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001345 }
1346 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001347}
1348
Neha Sharma96b7bf22020-06-15 10:37:32 +00001349func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001350 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 -07001351 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1352 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1353 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1354 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001355 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001356 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1357 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001358 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001359 onuInd.OperState = "down"
1360 }
1361 }
1362
David K. Bainbridge794735f2020-02-11 21:01:37 -08001363 switch onuInd.OperState {
1364 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001365 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 -07001366 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301367 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001368 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001369 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301370 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001371 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001372 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001373 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001374 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001376 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001377 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 -04001378 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301379 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001380 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001381 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301382 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001384 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001386 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001387 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001388 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001389 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001390 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001391 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001392}
1393
cuilin20187b2a8c32019-03-26 19:52:28 -07001394func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1395 if serialNum != nil {
1396 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001397 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001398 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001399}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001400func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1401 decodedStr, err := hex.DecodeString(serialNum[4:])
1402 if err != nil {
1403 return nil, err
1404 }
1405 return &oop.SerialNumber{
1406 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001407 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001408 }, nil
1409}
cuilin20187b2a8c32019-03-26 19:52:28 -07001410
1411func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001412 if len(vendorSpecific) > 3 {
1413 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1414 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1415 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1416 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1417 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1418 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1419 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1420 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1421 return tmp
1422 }
1423 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001424}
1425
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001426//UpdateFlowsBulk upates the bulk flow
1427func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301428 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001429}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001430
1431//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001432func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1433 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301434 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001435 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301436 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001437 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001438 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001439 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001440 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001441 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001442 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001443 "intf-id": parentPort,
1444 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001445 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001446 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 -08001447 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301448}
1449
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001450// SendPacketInToCore sends packet-in to core
1451// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1452// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001453func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001454 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001455 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001456 "port": logicalPort,
1457 "packet": hex.EncodeToString(packetPayload),
1458 "device-id": dh.device.Id,
1459 })
1460 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001461 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 +05301462 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001463 "source": "adapter",
1464 "destination": "core",
1465 "device-id": dh.device.Id,
1466 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001467 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001468 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001469 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001470 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001471 "packet": hex.EncodeToString(packetPayload),
1472 "device-id": dh.device.Id,
1473 })
1474 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001475 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001476}
1477
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001478// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001479func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001480 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001481
1482 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1483 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001484 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001485 }
1486
Kent Hagermane6ff1012020-07-14 15:07:53 -04001487 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001488 metrics := dh.metrics.GetSubscriberMetrics()
1489 for _, m := range pmConfigs.Metrics {
1490 metrics[m.Name].Enabled = m.Enabled
1491
1492 }
1493 }
1494}
1495
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001496//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301497func (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 +00001498 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 +01001499
Girish Gowdra491a9c62021-01-06 16:43:07 -08001500 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001501 var errorsList []error
1502
Girish Gowdru0c588b22019-04-23 23:24:56 -04001503 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001504 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001505 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001506
Neha Sharma96b7bf22020-06-15 10:37:32 +00001507 logger.Debugw(ctx, "removing-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 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001511 if flow_utils.HasGroup(flow) {
1512 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1513 } else {
1514 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1515 }
Girish Gowdracefae192020-03-19 18:14:10 -07001516 if err != nil {
1517 errorsList = append(errorsList, err)
1518 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001519 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301520
1521 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001522 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001523 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301524 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001525 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301526 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001527 if flow_utils.HasGroup(flow) {
1528 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1529 } else {
1530 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1531 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001532 if err != nil {
1533 errorsList = append(errorsList, err)
1534 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301535 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001536 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001537
Girish Gowdracefae192020-03-19 18:14:10 -07001538 // 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 +00001539 if groups != nil {
1540 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001541 // err = dh.groupMgr.AddGroup(ctx, group)
1542 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001543 if err != nil {
1544 errorsList = append(errorsList, err)
1545 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001546 }
1547 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001548 // err = dh.groupMgr.ModifyGroup(ctx, group)
1549 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001550 if err != nil {
1551 errorsList = append(errorsList, err)
1552 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001553 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001554 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001555 // err = dh.groupMgr.DeleteGroup(ctx, group)
1556 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001557 if err != nil {
1558 errorsList = append(errorsList, err)
1559 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001560 }
1561 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001562 if len(errorsList) > 0 {
1563 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1564 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001565 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001566 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301567}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001568
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001569//DisableDevice disables the given device
1570//It marks the following for the given device:
1571//Device-Handler Admin-State : down
1572//Device Port-State: UNKNOWN
1573//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001574func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001575 /* On device disable ,admin state update has to be done prior sending request to agent since
1576 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001577 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001578 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001579 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001580 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001581 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001582 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001583 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001584 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001585 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001586 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301587
1588 dh.discOnus = sync.Map{}
1589 dh.onus = sync.Map{}
1590
Thomas Lee S85f37312020-04-03 17:06:12 +05301591 //stopping the stats collector
1592 dh.stopCollector <- true
1593
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001595 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301596 //Update device Admin state
1597 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001598 // 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 +00001599 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 -04001600 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001601 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001602 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001603 return nil
1604}
1605
Neha Sharma96b7bf22020-06-15 10:37:32 +00001606func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001607 // Update onu state as unreachable in onu adapter
1608 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301609 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001610 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001611 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001612 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001613 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 -04001614 }
1615 if onuDevices != nil {
1616 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001617 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001618 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001619 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001620 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001621 "From Adapter": dh.openOLT.config.Topic, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001622 }
1623
1624 }
1625 }
1626
1627}
1628
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001629//ReenableDevice re-enables the olt device after disable
1630//It marks the following for the given device:
1631//Device-Handler Admin-State : up
1632//Device Port-State: ACTIVE
1633//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001634func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001635 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301636 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001637 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301638 }
1639 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001640 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001641
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001642 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001643
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001644 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1645 if err != nil {
divyadesai3af43e12020-08-18 07:10:54 +00001646 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001647 }
1648 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001649 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001650 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001651 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001652 device.OperStatus = voltha.OperStatus_ACTIVE
1653 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001654
Neha Sharma8f4e4322020-08-06 10:51:53 +00001655 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 +05301656 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001657 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001658 "connect-status": device.ConnectStatus,
1659 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001660 }
kesavand39e0aa32020-01-28 20:58:50 -05001661
Neha Sharma96b7bf22020-06-15 10:37:32 +00001662 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001663
1664 return nil
1665}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001666
npujarec5762e2020-01-01 14:08:48 +05301667func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001668 var uniID uint32
1669 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301670 for _, port := range onu.UniPorts {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001671 uniID = UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001672 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001673 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001674 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001675 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001676 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001677 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301678 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001679 for _, tpID := range tpIDList {
Girish Gowdraa482f272021-03-24 23:04:19 -07001680 if err = dh.resourceMgr.RemoveMeterInfoForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001681 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001682 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001683 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Girish Gowdraa482f272021-03-24 23:04:19 -07001684 if err = dh.resourceMgr.RemoveMeterInfoForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001685 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001686 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001687 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301688 }
npujarec5762e2020-01-01 14:08:48 +05301689 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1690 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001691 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301692 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001693 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001694 if err = dh.resourceMgr.DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001695 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 +00001696 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001697 if err = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID)); err != nil {
1698 logger.Debugw(ctx, "failed-to-remove-flow-for", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
1699 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001700 }
1701 return nil
1702}
1703
npujarec5762e2020-01-01 14:08:48 +05301704func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001705 nniUniID := -1
1706 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301707
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001708 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301709 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001710 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001711 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301712 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301713 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001714 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001715 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001716 logger.Debugw(ctx, "nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301717 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301718 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001719 _ = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, nniIntfID, -1, -1)
1720
Devmalya Paul495b94a2019-08-27 19:42:00 -04001721 }
npujarec5762e2020-01-01 14:08:48 +05301722 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001723 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301724 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001725
David K. Bainbridge794735f2020-02-11 21:01:37 -08001726 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001727}
1728
1729// 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 +05301730func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001731 logger.Debug(ctx, "function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001732 /* Clear the KV store data associated with the all the UNI ports
1733 This clears up flow data and also resource map data for various
1734 other pon resources like alloc_id and gemport_id
1735 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001736 go dh.cleanupDeviceResources(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001737 logger.Debug(ctx, "removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001738 // Stop the Stats collector
1739 dh.stopCollector <- true
1740 // stop the heartbeat check routine
1741 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301742 dh.lockDevice.RLock()
1743 // Stop the read indication only if it the routine is active
1744 if dh.isReadIndicationRoutineActive {
1745 dh.stopIndications <- true
1746 }
1747 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001748 //Reset the state
1749 if dh.Client != nil {
1750 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301751 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001752 }
1753 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08001754 dh.removeOnuIndicationChannels(ctx)
Girish Gowdrab1caa442020-10-19 12:24:39 -07001755 // There is no need to update the core about operation status and connection status of the OLT.
1756 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1757 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1758 // because the device does not exist in DB.
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001759 return nil
1760}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001761func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001762
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001763 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301764 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001765 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301766 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301767 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301768 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001769 _ = olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001770 "device-id": dh.device.Id,
Kent Hagermane6ff1012020-07-14 15:07:53 -04001771 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301772 }
1773 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301774 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001775 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301776 if err = dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001777 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301778 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301779 // Clear flowids for gem cache.
1780 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301781 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301782 }
1783 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301784 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301785 }
npujarec5762e2020-01-01 14:08:48 +05301786 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301787 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301788 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301789 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001790 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001791 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001792 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001793 /* Clear the flows from KV store associated with NNI port.
1794 There are mostly trap rules from NNI port (like LLDP)
1795 */
npujarec5762e2020-01-01 14:08:48 +05301796 if err := dh.clearNNIData(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001797 logger.Errorw(ctx, "failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001798 }
A R Karthick1f85b802019-10-11 05:06:05 +00001799
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001800 /* Clear the resource pool for each PON port in the background */
Kent Hagermane6ff1012020-07-14 15:07:53 -04001801 go func() {
1802 if err := dh.resourceMgr.Delete(ctx); err != nil {
1803 logger.Debug(ctx, err)
1804 }
1805 }()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001806 }
A R Karthick1f85b802019-10-11 05:06:05 +00001807
Devmalya Paul495b94a2019-08-27 19:42:00 -04001808 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301809 dh.onus.Range(func(key interface{}, value interface{}) bool {
1810 dh.onus.Delete(key)
1811 return true
1812 })
1813
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001814 /*Delete discovered ONU map for the device*/
1815 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1816 dh.discOnus.Delete(key)
1817 return true
1818 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001819}
1820
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001821//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001822func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001823 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301824 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001825 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001826 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001827 return nil
1828}
1829
David K. Bainbridge794735f2020-02-11 21:01:37 -08001830func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001831 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001832 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001833 "packet-indication": *packetIn,
1834 "device-id": dh.device.Id,
1835 "packet": hex.EncodeToString(packetIn.Pkt),
1836 })
1837 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001838 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001839 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001840 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001841 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001842 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001843 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001844 "logical-port-num": logicalPortNum,
1845 "device-id": dh.device.Id,
1846 "packet": hex.EncodeToString(packetIn.Pkt),
1847 })
1848 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849
Neha Sharma8f4e4322020-08-06 10:51:53 +00001850 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 +05301851 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001852 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301853 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001854 "device-id": dh.device.Id,
1855 "packet": hex.EncodeToString(packetIn.Pkt),
1856 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001857 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001858
Matteo Scandolo92186242020-06-12 10:54:18 -07001859 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001860 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001861 "packet": hex.EncodeToString(packetIn.Pkt),
1862 "device-id": dh.device.Id,
1863 })
1864 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001865 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001866}
1867
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001868// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301869func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001870 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001871 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001872 "device-id": dh.device.Id,
1873 "egress-port-no": egressPortNo,
1874 "pkt-length": len(packet.Data),
1875 "packet": hex.EncodeToString(packet.Data),
1876 })
1877 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001878
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001879 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001880 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001881 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1882 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301883 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1884 // Do not packet-out lldp packets on uni port.
1885 // ONOS has no clue about uni/nni ports, it just packets out on all
1886 // available ports on the Logical Switch. It should not be interested
1887 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001888 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001889 "device-id": dh.device.Id,
1890 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301891 return nil
1892 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001893 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1894 if innerEthType == 0x8100 {
1895 // q-in-q 802.1ad or 802.1q double tagged packet.
1896 // slice out the outer tag.
1897 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001898 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001899 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001900 "packet-data": hex.EncodeToString(packet.Data),
1901 "device-id": dh.device.Id,
1902 })
1903 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001904 }
1905 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001906 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1907 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001908 uniID := UniIDFromPortNum(uint32(egressPortNo))
1909
Girish Gowdra9602eb42020-09-09 15:50:39 -07001910 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001911 if err != nil {
1912 // In this case the openolt agent will receive the gemPortID as 0.
1913 // The agent tries to retrieve the gemPortID in this case.
1914 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001915 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001916 "intf-id": intfID,
1917 "onu-id": onuID,
1918 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001919 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301920 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001921 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001922 }
1923
1924 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07001925 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001926 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001927 "egress-port-no": egressPortNo,
1928 "intf-id": intfID,
1929 "onu-id": onuID,
1930 "uni-id": uniID,
1931 "gem-port-id": gemPortID,
1932 "packet": hex.EncodeToString(packet.Data),
1933 "device-id": dh.device.Id,
1934 })
1935 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001936
npujarec5762e2020-01-01 14:08:48 +05301937 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301938 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001939 "source": "adapter",
1940 "destination": "onu",
1941 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001942 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001943 "oni-id": onuID,
1944 "uni-id": uniID,
1945 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001946 "packet": hex.EncodeToString(packet.Data),
1947 "device-id": dh.device.Id,
1948 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001949 }
1950 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001951 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001952 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001953 return olterrors.NewErrInvalidValue(log.Fields{
1954 "egress-nni-port": egressPortNo,
1955 "device-id": dh.device.Id,
1956 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001957 }
1958 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001959
Matteo Scandolo92186242020-06-12 10:54:18 -07001960 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001961 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001962 "uplink-pkt": uplinkPkt,
1963 "packet": hex.EncodeToString(packet.Data),
1964 "device-id": dh.device.Id,
1965 })
1966 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001967
npujarec5762e2020-01-01 14:08:48 +05301968 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001969 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1970 "packet": hex.EncodeToString(packet.Data),
1971 "device-id": dh.device.Id,
1972 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001973 }
1974 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001975 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301976 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001977 "egressPortType": egressPortType,
1978 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301979 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001980 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001981 }
1982 return nil
1983}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001984
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001985func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1986 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001987}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301988
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001989func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001990
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301991 // start the heartbeat check towards the OLT.
1992 var timerCheck *time.Timer
1993
1994 for {
1995 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1996 select {
1997 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00001998 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001999 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002000 logger.Warnw(ctx, "hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302001 if timerCheck == nil {
2002 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002003 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302004 }
2005 } else {
2006 if timerCheck != nil {
2007 if timerCheck.Stop() {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002008 logger.Debugw(ctx, "got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302009 }
2010 timerCheck = nil
2011 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002012 logger.Debugw(ctx, "hearbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302013 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302014 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302015 }
2016 cancel()
2017 case <-dh.stopHeartbeatCheck:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002018 logger.Debugw(ctx, "stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302019 return
2020 }
2021 }
2022}
2023
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002024func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
2025 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
2026 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002027 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2028 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2029 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2030 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2031 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002032 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002033 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2034 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002035 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302036
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002037 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
2038 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002039 _ = 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 -04002040 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002041 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002042 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002043 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002044
2045 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002046 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00002047 device.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2048 device.OperStatus = voltha.OperStatus_UNKNOWN
2049 go dh.eventMgr.oltCommunicationEvent(ctx, device, raisedTs)
2050
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002051 go dh.cleanupDeviceResources(ctx)
2052
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002053 dh.lockDevice.RLock()
2054 // Stop the read indication only if it the routine is active
2055 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2056 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2057 // on next execution of the readIndication routine.
2058 if dh.isReadIndicationRoutineActive {
2059 dh.stopIndications <- true
2060 }
2061 dh.lockDevice.RUnlock()
2062
Gamze Abakac2c32a62021-03-11 11:44:18 +00002063 //reset adapter reconcile flag
2064 dh.adapterPreviouslyConnected = false
2065
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002066 dh.transitionMap.Handle(ctx, DeviceInit)
2067
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302068 }
2069}
kesavand39e0aa32020-01-28 20:58:50 -05002070
2071// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002072func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2073 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2074 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002075}
2076
2077// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002078func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2079 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2080 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002081}
2082
kdarapu1afeceb2020-02-12 01:38:09 -05002083//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 +00002084func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2085 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002086 if port.GetType() == voltha.Port_ETHERNET_NNI {
2087 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002088 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302089 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302090 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002091 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002092 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002093 }
2094 // fetch interfaceid from PortNo
2095 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2096 ponIntf := &oop.Interface{IntfId: ponID}
2097 var operStatus voltha.OperStatus_Types
2098 if enablePort {
2099 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302100 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002101
2102 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302103 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002104 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002105 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002106 }
2107 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002108 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002109 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002110 } else {
2111 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302112 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002113 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302114 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002115 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002116 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002117 }
2118 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002119 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002120 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002121 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302122 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 +05302123 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302124 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002125 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002126 }
2127 return nil
2128}
2129
kdarapu1afeceb2020-02-12 01:38:09 -05002130//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002131func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002132 // Disable the port and update the oper_port_status to core
2133 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002134 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002135 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002136 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302137 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302138 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002139 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002140 }
2141 }
2142 }
2143 return nil
2144}
2145
2146//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002147func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2148 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2149 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002150 if port.Type == voltha.Port_ETHERNET_NNI {
2151 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002152 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002153 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002154 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002155 }
2156 }
2157 if port.Type == voltha.Port_PON_OLT {
2158 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002159 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002160 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002161 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002162 }
2163 }
2164 }
2165}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002166
2167// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002168func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002169 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002170 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2171 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002172
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002173 var sn *oop.SerialNumber
2174 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002175 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302176 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002177 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302178 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002179 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002180 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002181
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002182 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Neha Sharma8f4e4322020-08-06 10:51:53 +00002183 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302184 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302185 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002186 "onu-id": onuID}, err).Log()
2187 }
2188 //clear PON resources associated with ONU
2189 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002190 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002191 logger.Warnw(ctx, "failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002192 "device-id": dh.device.Id,
2193 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002194 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002195 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002196 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002197 "device-id": dh.device.Id,
2198 "intf-id": intfID,
2199 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002200 } else {
2201 for i, onu := range onuGemData {
Girish Gowdraa0870562021-03-11 14:30:14 -08002202 if onu.OnuID == onuID && onu.SerialNumber == onuSn {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002203 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002204 if err := dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002205 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302206 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002207 "onu-device": onu,
2208 "error": err})
2209 }
2210 // Clear flowids for gem cache.
2211 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002212 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002213 }
2214 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002215 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002216 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002217 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002218 "intf-id": intfID,
2219 "onu-device": onu,
2220 "onu-gem": onuGemData,
2221 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002222 //Not returning error on cleanup.
2223 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002224 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002225 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002226 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002227 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002228 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002229 }
2230 }
2231 dh.onus.Delete(onuKey)
Girish Gowdraa0870562021-03-11 14:30:14 -08002232 dh.discOnus.Delete(onuSn)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002233 return nil
2234}
Girish Gowdracefae192020-03-19 18:14:10 -07002235
2236func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002237 for _, field := range flow_utils.GetOfbFields(flow) {
2238 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002239 return field.GetPort()
2240 }
2241 }
2242 return InvalidPort
2243}
2244
2245func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002246 for _, action := range flow_utils.GetActions(flow) {
2247 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002248 if out := action.GetOutput(); out != nil {
2249 return out.GetPort()
2250 }
2251 }
2252 }
2253 return InvalidPort
2254}
2255
Girish Gowdracefae192020-03-19 18:14:10 -07002256func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2257 inPort := getInPortFromFlow(flow)
2258 outPort := getOutPortFromFlow(flow)
2259
2260 if inPort == InvalidPort || outPort == InvalidPort {
2261 return inPort, outPort
2262 }
2263
2264 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2265 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2266 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002267 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002268 return uniPort, outPort
2269 }
2270 }
2271 } else {
2272 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2273 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002274 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002275 return inPort, uniPort
2276 }
2277 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2278 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002279 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002280 return uniPort, outPort
2281 }
2282 }
2283 }
2284
2285 return InvalidPort, InvalidPort
2286}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002287
2288func extractOmciTransactionID(omciPkt []byte) uint16 {
2289 if len(omciPkt) > 3 {
2290 d := omciPkt[0:2]
2291 transid := binary.BigEndian.Uint16(d)
2292 return transid
2293 }
2294 return 0
2295}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002296
2297// StoreOnuDevice stores the onu parameters to the local cache.
2298func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2299 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2300 dh.onus.Store(onuKey, onuDevice)
2301}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002302
Neha Sharma8f4e4322020-08-06 10:51:53 +00002303func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002304 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002305 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002306 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002307 resp := new(voltha.ReturnValues)
2308 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002309 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002310 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002311 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2312 return nil, err
2313 }
2314 ID = device.ProxyAddress.GetOnuId()
2315 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2316 valueparam.Onu = &Onu
2317 valueparam.Value = value
2318
2319 // This API is unsupported until agent patch is added
2320 resp.Unsupported = uint32(value)
2321 _ = ctx
2322
2323 // Uncomment this code once agent changes are complete and tests
2324 /*
2325 resp, err = dh.Client.GetValue(ctx, valueparam)
2326 if err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002327 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002328 return nil, err
2329 }
2330 */
2331
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002332 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 -08002333 return resp, nil
2334}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002335
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002336func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002337 // Default to PON0
2338 var intfID uint32
2339 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002340 if inPort != InvalidPort && outPort != InvalidPort {
2341 _, intfID, _, _ = ExtractAccessFromFlow(inPort, outPort)
2342 }
2343 return intfID
2344}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002345
Mahir Gunyelb0046752021-02-26 13:51:05 -08002346func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2347 dh.perPonOnuIndicationChannelLock.Lock()
2348 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2349 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002350 return ch.indicationChannel
2351 }
2352 channels := onuIndicationChannels{
2353 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002354 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002355 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002356 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002357 stopChannel: make(chan struct{}),
2358 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002359 dh.perPonOnuIndicationChannel[intfID] = channels
2360 dh.perPonOnuIndicationChannelLock.Unlock()
2361 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002362 return channels.indicationChannel
2363
2364}
2365
Mahir Gunyelb0046752021-02-26 13:51:05 -08002366func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2367 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2368 dh.perPonOnuIndicationChannelLock.Lock()
2369 defer dh.perPonOnuIndicationChannelLock.Unlock()
2370 for _, v := range dh.perPonOnuIndicationChannel {
2371 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002372 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002373 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002374}
2375
Mahir Gunyelb0046752021-02-26 13:51:05 -08002376func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2377 ind := onuIndicationMsg{
2378 ctx: ctx,
2379 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002380 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002381 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002382 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002383 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002384}
2385
Mahir Gunyelb0046752021-02-26 13:51:05 -08002386func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002387 for {
2388 select {
2389 // process one indication per onu, before proceeding to the next one
2390 case onuInd := <-onuChannels.indicationChannel:
2391 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Mahir Gunyelb0046752021-02-26 13:51:05 -08002392 "ind": onuInd.indication})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002393 switch onuInd.indication.Data.(type) {
2394 case *oop.Indication_OnuInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002395 if err := dh.onuIndication(onuInd.ctx, onuInd.indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002396 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2397 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002398 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002399 }
2400 case *oop.Indication_OnuDiscInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002401 if err := dh.onuDiscIndication(onuInd.ctx, onuInd.indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002402 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2403 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002404 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002405 }
2406 }
2407 case <-onuChannels.stopChannel:
2408 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2409 close(onuChannels.indicationChannel)
2410 return
2411 }
2412 }
2413}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002414
2415// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2416// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
2417func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *voltha.OfpFlowStats, group *voltha.OfpGroupEntry, action string) error {
2418 // Step1 : Fill McastFlowOrGroupControlBlock
2419 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2420 // Step3 : Wait on response channel for response
2421 // Step4 : Return error value
2422 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2423 errChan := make(chan error)
2424 var groupID uint32
2425 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2426 ctx: ctx,
2427 flowOrGroupAction: action,
2428 flow: flow,
2429 group: group,
2430 errChan: &errChan,
2431 }
2432 if flow != nil {
2433 groupID = flow_utils.GetGroup(flow)
2434 } else if group != nil {
2435 groupID = group.Desc.GroupId
2436 } else {
2437 return errors.New("flow-and-group-both-nil")
2438 }
2439 // Derive the appropriate go routine to handle the request by a simple module operation.
2440 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2441 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2442 // Wait for handler to return error value
2443 err := <-errChan
2444 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"flow": flow, "group": group, "action": action, "err": err})
2445 return err
2446}
2447
2448// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
2449func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock) {
2450 for {
2451 // block on the channel to receive an incoming mcast flow/group
2452 // process the flow completely before proceeding to handle the next flow
2453 mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel
2454 if mcastFlowOrGroupCb.flow != nil {
2455 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2456 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2457 log.Fields{"device-id": dh.device.Id,
2458 "flowToAdd": mcastFlowOrGroupCb.flow})
2459 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2460 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2461 // Pass the return value over the return channel
2462 *mcastFlowOrGroupCb.errChan <- err
2463 } else { // flow remove
2464 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2465 log.Fields{"device-id": dh.device.Id,
2466 "flowToRemove": mcastFlowOrGroupCb.flow})
2467 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2468 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2469 // Pass the return value over the return channel
2470 *mcastFlowOrGroupCb.errChan <- err
2471 }
2472 } else { // mcast group
2473 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2474 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2475 log.Fields{"device-id": dh.device.Id,
2476 "groupToAdd": mcastFlowOrGroupCb.group})
2477 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2478 // Pass the return value over the return channel
2479 *mcastFlowOrGroupCb.errChan <- err
2480 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2481 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2482 log.Fields{"device-id": dh.device.Id,
2483 "groupToModify": mcastFlowOrGroupCb.group})
2484 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2485 // Pass the return value over the return channel
2486 *mcastFlowOrGroupCb.errChan <- err
2487 } else { // group remove
2488 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2489 log.Fields{"device-id": dh.device.Id,
2490 "groupToRemove": mcastFlowOrGroupCb.group})
2491 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2492 // Pass the return value over the return channel
2493 *mcastFlowOrGroupCb.errChan <- err
2494 }
2495 }
2496 }
2497}
kesavand62126212021-01-12 04:56:06 -05002498
2499func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2500
2501 singleValResp := extension.SingleGetValueResponse{
2502 Response: &extension.GetValueResponse{
2503 Response: &extension.GetValueResponse_PortCoutners{
2504 PortCoutners: &extension.GetOltPortCountersResponse{},
2505 },
2506 },
2507 }
2508
2509 errResp := func(status extension.GetValueResponse_Status,
2510 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2511 return &extension.SingleGetValueResponse{
2512 Response: &extension.GetValueResponse{
2513 Status: status,
2514 ErrReason: reason,
2515 },
2516 }
2517 }
2518
2519 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2520 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2521 //send error response
2522 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2523 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2524 }
2525 statIndChn := make(chan bool, 1)
2526 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2527 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2528 //request openOlt agent to send the the port statistics indication
2529
2530 go func() {
2531 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2532 if err != nil {
2533 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2534 }
2535 }()
2536 select {
2537 case <-statIndChn:
2538 //indication received for ports stats
2539 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2540 case <-time.After(oltPortInfoTimeout * time.Second):
2541 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2542 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2543 case <-ctx.Done():
2544 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2545 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2546 }
2547 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2548 //get nni stats
2549 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
2550 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2551 cmnni := dh.portStats.collectNNIMetrics(intfID)
2552 if cmnni == nil {
2553 //TODO define the error reason
2554 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2555 }
2556 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2557 return &singleValResp
2558
2559 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2560 // get pon stats
2561 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
2562 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2563 cmpon := dh.portStats.collectPONMetrics(intfID)
2564 if cmpon == nil {
2565 //TODO define the error reason
2566 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2567 }
2568 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2569 return &singleValResp
2570 }
2571 }
2572 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2573}