blob: d998dbb1f654f83a174106c4029da632eb9c8ee1 [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
David Bainbridgef5879ca2019-12-13 21:17:54 +0000368 // Create an exponential backoff around re-enabling indications. The
369 // maximum elapsed time for the back off is set to 0 so that we will
370 // continue to retry. The max interval defaults to 1m, but is set
371 // here for code clarity
372 indicationBackoff := backoff.NewExponentialBackOff()
373 indicationBackoff.MaxElapsedTime = 0
374 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700375
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700376 dh.lockDevice.Lock()
377 dh.isReadIndicationRoutineActive = true
378 dh.lockDevice.Unlock()
379
Girish Gowdra3f974912020-03-23 20:35:18 -0700380Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700381 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400382 select {
383 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000384 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700385 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400386 default:
387 indication, err := indications.Recv()
388 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000389 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530390 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530391 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400392 // Use an exponential back off to prevent getting into a tight loop
393 duration := indicationBackoff.NextBackOff()
394 if duration == backoff.Stop {
395 // If we reach a maximum then warn and reset the backoff
396 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000397 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530398 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530399 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400400 indicationBackoff.Reset()
401 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700402
403 // On failure process a backoff timer while watching for stopIndications
404 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700405 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700406 select {
407 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000408 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700409 if !backoffTimer.Stop() {
410 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700411 }
412 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700413 case <-backoffTimer.C:
414 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700415 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700416 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
417 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400418 }
419 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000420 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530421 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000422 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530423 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530424 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700425 // Close the stream, and re-initialize it
426 if err = indications.CloseSend(); err != nil {
427 // Ok to ignore here, because we landed here due to a problem on the stream
428 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000429 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530430 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530431 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700432 }
Matteo Scandolof16389e2021-05-18 00:47:08 +0000433 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700434 return err
435 }
436 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400437 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530438 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400439 // Reset backoff if we have a successful receive
440 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400441 // When OLT is admin down, ignore all indications.
Girish Gowdra852ad912021-05-04 00:05:50 -0700442 if dh.device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000443 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530444 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530445 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400446 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400447 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400448 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700449 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700450 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700451 // Close the send stream
452 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700453
Girish Gowdra3f974912020-03-23 20:35:18 -0700454 return nil
455}
456
457func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
Girish Gowdra852ad912021-05-04 00:05:50 -0700458 logger.Infow(ctx, "enabling read indications", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700459 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
460 if err != nil {
461 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
462 }
463 if indications == nil {
464 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
465 }
Girish Gowdra852ad912021-05-04 00:05:50 -0700466 logger.Infow(ctx, "read indication started successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700467 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400468}
469
470// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
471func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
472 switch indication.Data.(type) {
473 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
474 return true
475
476 default:
477 return false
478 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700479}
480
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700482 raisedTs := time.Now().Unix()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000483 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530484 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700485 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530486 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700487 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000488 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000489 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530490 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000491 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800492 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000493 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800494 }
495 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700496}
497
David K. Bainbridge794735f2020-02-11 21:01:37 -0800498// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530499func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700500 raisedTs := time.Now().Unix()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700501 switch indication.Data.(type) {
502 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000503 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
504 defer span.Finish()
Girish Gowdra852ad912021-05-04 00:05:50 -0700505 logger.Infow(ctx, "received olt indication", log.Fields{"device-id": dh.device.Id, "olt-ind": indication.GetOltInd()})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800506 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400507 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800508 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700509 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000510 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
511 defer span.Finish()
512
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700513 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800514 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000515 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400516 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800517 }
518 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000519 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700520 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000521 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
522 defer span.Finish()
523
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700524 intfOperInd := indication.GetIntfOperInd()
525 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800526 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000527 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400528 _ = 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 -0800529 }
530 }()
Kent Hagermane6ff1012020-07-14 15:07:53 -0400531 if err := dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId()); err != nil {
532 logger.Warn(ctx, err)
533 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700534 } else if intfOperInd.GetType() == "pon" {
535 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
536 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800537 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000538 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400539 _ = 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 -0800540 }
541 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000542 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700543 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000544 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530545 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530546 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700547 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000548 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
549 defer span.Finish()
550
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700551 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000552 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800553 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800554 dh.putOnuIndicationToChannel(ctx, indication, onuDiscInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000556 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
557 defer span.Finish()
558
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700559 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800561 //put message to channel and return immediately
Mahir Gunyelb0046752021-02-26 13:51:05 -0800562 dh.putOnuIndicationToChannel(ctx, indication, onuInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700563 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000564 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
565 defer span.Finish()
566
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700567 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000568 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 -0800569 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000570 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400571 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800572 }
573 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700574 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000575 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
576 defer span.Finish()
577
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700578 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000579 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700580 "intf-type": pktInd.IntfId,
581 "intf-id": pktInd.IntfId,
582 "gem-port-id": pktInd.GemportId,
583 "port-no": pktInd.PortNo,
584 "device-id": dh.device.Id,
585 })
586
587 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000588 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700589 "intf-type": pktInd.IntfId,
590 "intf-id": pktInd.IntfId,
591 "gem-port-id": pktInd.GemportId,
592 "port-no": pktInd.PortNo,
593 "packet": hex.EncodeToString(pktInd.Pkt),
594 "device-id": dh.device.Id,
595 })
596 }
597
David K. Bainbridge794735f2020-02-11 21:01:37 -0800598 go func() {
599 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400600 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800601 }
602 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700603 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000604 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
605 defer span.Finish()
606
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700607 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700608 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000610 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
611 defer span.Finish()
612
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700613 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000614 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700615 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000616 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
617 defer span.Finish()
618
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700619 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000620 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
621 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700622 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530623}
624
625// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530626func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530627 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000628 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530629
Girish Gowdru0c588b22019-04-23 23:24:56 -0400630 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530631 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400632 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000633 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400634 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000635
636 //Clear olt communication failure event
637 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
638 dh.device.OperStatus = voltha.OperStatus_ACTIVE
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700639 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +0000640 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
641
Gamze Abakac2c32a62021-03-11 11:44:18 +0000642 //check adapter and agent reconcile status
643 //reboot olt if needed (olt disconnection case)
644 if dh.adapterPreviouslyConnected != dh.agentPreviouslyConnected {
645 logger.Warnw(ctx, "different-reconcile-status-between-adapter-and-agent-rebooting-device",
646 log.Fields{
647 "device-id": dh.device.Id,
648 "adapter-status": dh.adapterPreviouslyConnected,
649 "agent-status": dh.agentPreviouslyConnected,
650 })
651 _ = dh.RebootDevice(ctx, dh.device)
652 }
653
Girish Gowdru0c588b22019-04-23 23:24:56 -0400654 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530655}
656
657// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530658func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000659 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400660
npujarec5762e2020-01-01 14:08:48 +0530661 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400662 if err != nil || device == nil {
663 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000664 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400665 }
666
667 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400668
669 //Update the device oper state and connection status
670 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800671 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400672 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800673 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400674
David K. Bainbridge794735f2020-02-11 21:01:37 -0800675 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000676 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400677 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400678
679 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530680 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400681 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000682 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400683 }
684 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400685 // Update onu state as down in onu adapter
686 onuInd := oop.OnuIndication{}
687 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800688 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +0300689 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800690 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400691 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +0300692 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800693 "onu-indicator": onuInd,
694 "device-type": onuDevice.Type,
695 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700696 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800697 } else {
698 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 -0700699 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400700 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800701 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700702 /* Discovered ONUs entries need to be cleared , since after OLT
703 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530704 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800705 dh.lockDevice.Unlock()
706
Neha Sharma96b7bf22020-06-15 10:37:32 +0000707 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700708 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530709}
710
711// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530712func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400713 var err error
Gamze Abaka49c40b32021-05-06 09:30:41 +0000714
715 // if the connection is already available, close the previous connection (olt reboot case)
716 if dh.clientCon != nil {
717 if err = dh.clientCon.Close(); err != nil {
718 logger.Errorw(ctx, "failed-to-close-previous-connection", log.Fields{"device-id": dh.device.Id})
719 } else {
720 logger.Debugw(ctx, "previous-grpc-channel-closed-successfully", log.Fields{"device-id": dh.device.Id})
721 }
722 }
723
724 // Use Interceptors to automatically inject and publish Open Tracing Spans by this GRPC client
Girish Kumar93e91742020-07-27 16:43:19 +0000725 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
726 grpc.WithInsecure(),
727 grpc.WithBlock(),
728 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000729 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000730 )),
731 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000732 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000733 )))
734
735 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530736 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530737 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000738 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400739 }
740 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530741}
742
743// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530744func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400745 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530746 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400747 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530748}
749
750// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530751func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530752 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000753 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400754
755 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530756 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
757 if err != nil || device == nil {
758 /*TODO: needs to handle error scenarios */
759 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
760 }
761 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000762 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400763
764 cloned := proto.Clone(device).(*voltha.Device)
765 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
766 cloned.OperStatus = voltha.OperStatus_UNKNOWN
767 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530768 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
769 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 -0400770 }
771
Chaitrashree G S44124192019-08-07 20:21:36 -0400772 // 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 +0530773 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400774 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530775 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400776 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400777 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
778 // all the modules initialized and ready to handle incoming ONUs.
779
Thomas Lee S985938d2020-05-04 11:40:41 +0530780 err = dh.initializeDeviceHandlerModules(ctx)
781 if err != nil {
782 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 -0400783 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400784
785 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800786 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530787 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400788 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800789 }
790 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700791
792 go startHeartbeatCheck(ctx, dh)
793
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400794 return nil
795 }
796
Neha Sharma8f4e4322020-08-06 10:51:53 +0000797 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400798 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400799 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400800 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400801 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400802 dh.populateActivePorts(ctx, ports)
803 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
804 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400805 }
806
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400807 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530808 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 -0400809 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530810
cuilin20187b2a8c32019-03-26 19:52:28 -0700811 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800812 go func() {
813 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400814 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800815 }
816 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000817 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000818
819 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000820 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000821 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700822
823 go startHeartbeatCheck(ctx, dh)
824
cuilin20187b2a8c32019-03-26 19:52:28 -0700825 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530826}
827
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400828func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000829 deviceInfo, err := dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400830
831 if err != nil {
832 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
833 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700834 dh.totalPonPorts = deviceInfo.GetPonPorts()
Gamze Abakac2c32a62021-03-11 11:44:18 +0000835 dh.agentPreviouslyConnected = deviceInfo.PreviouslyConnected
Girish Gowdra9602eb42020-09-09 15:50:39 -0700836
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400837 // Instantiate resource manager
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800838 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 -0400839 return olterrors.ErrResourceManagerInstantiating
840 }
841
Girish Gowdra9602eb42020-09-09 15:50:39 -0700842 dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400843
Girish Gowdra9602eb42020-09-09 15:50:39 -0700844 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
845 for i := range dh.flowMgr {
846 // Instantiate flow manager
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700847 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr, dh.groupMgr, uint32(i)); dh.flowMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700848 return olterrors.ErrResourceManagerInstantiating
849 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400850 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700851
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400852 /* TODO: Instantiate Alarm , stats , BW managers */
853 /* Instantiating Event Manager to handle Alarms and KPIs */
854 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
855
856 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000857 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400858
859 return nil
860
861}
862
Neha Sharma96b7bf22020-06-15 10:37:32 +0000863func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400864 var err error
865 var deviceInfo *oop.DeviceInfo
866
Neha Sharma8f4e4322020-08-06 10:51:53 +0000867 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400868
869 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000870 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400871 }
872 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000873 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400874 }
875
Neha Sharma96b7bf22020-06-15 10:37:32 +0000876 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400877 dh.device.Root = true
878 dh.device.Vendor = deviceInfo.Vendor
879 dh.device.Model = deviceInfo.Model
880 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
881 dh.device.HardwareVersion = deviceInfo.HardwareVersion
882 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
883
884 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000885 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400886 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000887 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400888 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000889 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400890 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000891 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400892 dh.device.MacAddress = genmac
893 } else {
894 dh.device.MacAddress = deviceInfo.DeviceId
895 }
896
897 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000898 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000899 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400900 }
901
902 return deviceInfo, nil
903}
904
Neha Sharma96b7bf22020-06-15 10:37:32 +0000905func startCollector(ctx context.Context, dh *DeviceHandler) {
Matteo Scandolo861e06e2021-05-26 11:51:46 -0700906 logger.Debugw(ctx, "starting-collector", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530907 for {
908 select {
909 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000910 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530911 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000912 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700913
Neha Sharma8f4e4322020-08-06 10:51:53 +0000914 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400915 if err != nil {
916 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
917 continue
918 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530919 for _, port := range ports {
920 // NNI Stats
921 if port.Type == voltha.Port_ETHERNET_NNI {
922 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
923 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000924 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000925 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000926 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530927 }
928 // PON Stats
929 if port.Type == voltha.Port_PON_OLT {
930 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
931 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
932 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000933 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000934 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530935 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000936 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000937
938 //ONU & Gem Stats
939 onuGemInfo := dh.flowMgr[intfID].onuGemInfo
940 if len(onuGemInfo) != 0 {
941 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfo)
942 }
Chaitrashree G Sef088112020-02-03 21:39:27 -0500943 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530944 }
945 }
946 }
947}
948
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700949//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530950func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400951 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000952 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530953 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530954
955 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400956 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
957 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530958 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530959}
960
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700961//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530962func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700963 return &ic.SwitchCapability{
964 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530965 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700966 HwDesc: "open_pon",
967 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700968 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -0700969 },
970 SwitchFeatures: &of.OfpSwitchFeatures{
971 NBuffers: 256,
972 NTables: 2,
973 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
974 of.OfpCapabilities_OFPC_TABLE_STATS |
975 of.OfpCapabilities_OFPC_PORT_STATS |
976 of.OfpCapabilities_OFPC_GROUP_STATS),
977 },
978 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530979}
980
Neha Sharma96b7bf22020-06-15 10:37:32 +0000981func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
982 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 -0700983 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700984 var deviceID string
985 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700986
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400987 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700988 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000989 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 -0700990 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
991 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400992
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700993 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530994
995 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
996
Neha Sharma96b7bf22020-06-15 10:37:32 +0000997 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 -0700998 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700999 kwargs := make(map[string]interface{})
1000 kwargs["onu_id"] = omciInd.OnuId
1001 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -07001002
Neha Sharma8f4e4322020-08-06 10:51:53 +00001003 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001004 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301005 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001006 "intf-id": omciInd.IntfId,
1007 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001008 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001009 deviceType = onuDevice.Type
1010 deviceID = onuDevice.Id
1011 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
1012 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301013 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001014 } else {
1015 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +00001016 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 +05301017 deviceType = onuInCache.(*OnuDevice).deviceType
1018 deviceID = onuInCache.(*OnuDevice).deviceID
1019 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -07001020 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001021
1022 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +00001023 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001024 ic.InterAdapterMessageType_OMCI_REQUEST, dh.openOLT.config.Topic, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001025 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301026 return olterrors.NewErrCommunication("omci-request", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001027 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028 "destination": deviceType,
1029 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001030 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001031 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001032 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301033}
1034
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001035//ProcessInterAdapterMessage sends the proxied messages to the target device
1036// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1037// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001038func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
1039 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001040 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001041 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -07001042 fromTopic := msg.Header.FromTopic
1043 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001044 toDeviceID := msg.Header.ToDeviceId
1045 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -07001046
Neha Sharma96b7bf22020-06-15 10:37:32 +00001047 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 -07001048
1049 msgBody := msg.GetBody()
1050
1051 omciMsg := &ic.InterAdapterOmciMessage{}
1052 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001053 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001054 }
1055
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001056 if omciMsg.GetProxyAddress() == nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001057 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001058 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301059 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001060 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001061 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001062 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001063 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1064 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301065 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001066 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001067 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001069 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001070 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1071 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301072 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001073 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001074 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001075 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001076 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001077 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001078 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001079 }
1080 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301081}
1082
Neha Sharma96b7bf22020-06-15 10:37:32 +00001083func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084 var intfID uint32
1085 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001086 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001087 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001088 intfID = onuDevice.ProxyAddress.GetChannelId()
1089 onuID = onuDevice.ProxyAddress.GetOnuId()
1090 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001091 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001092 intfID = omciMsg.GetProxyAddress().GetChannelId()
1093 onuID = omciMsg.GetProxyAddress().GetOnuId()
1094 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001095 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001096 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001097 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 -08001098
Thomas Lee S94109f12020-03-03 16:39:29 +05301099 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001100 "intf-id": intfID,
1101 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001102 }
1103
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001104 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1105 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001106 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001107 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1108 hex.Encode(hexPkt, omciMsg.Message)
1109 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1110
1111 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1112 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1113 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001114 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001115 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001116
Neha Sharma8f4e4322020-08-06 10:51:53 +00001117 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001118 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301119 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001120 "intf-id": intfID,
1121 "onu-id": onuID,
1122 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001123 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001124 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001125}
1126
David K. Bainbridge794735f2020-02-11 21:01:37 -08001127func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301128 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 -07001129 if err := dh.flowMgr[intfID].UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001130 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001131 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001132 // TODO: need resource manager
1133 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301134 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301135 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001136 st, _ := status.FromError(err)
1137 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1139
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001140 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301141 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001142 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001143 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001144 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001145 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001146 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001147}
1148
Mahir Gunyelb0046752021-02-26 13:51:05 -08001149func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001150 channelID := onuDiscInd.GetIntfId()
1151 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001152
Mahir Gunyelb0046752021-02-26 13:51:05 -08001153 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001154 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301155
cuilin20187b2a8c32019-03-26 19:52:28 -07001156 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001157 if sn != "" {
1158 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001159 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001160 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001161 }
1162
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301163 var alarmInd oop.OnuAlarmIndication
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001164 raisedTs := time.Now().Unix()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001165 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301166
1167 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1168 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1169 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1170 OnuLosRaise event sent for it */
1171 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1172 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1173 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001174 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301175 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1176 "currentIntfId": onuDiscInd.GetIntfId()})
1177 // TODO:: Should we need to ignore raising OnuLosClear event
1178 // when onu connected to different PON?
1179 }
1180 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1181 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1182 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001183 go func() {
1184 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1185 logger.Debugw(ctx, "indication-failed", log.Fields{"error": err})
1186 }
1187 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301188 }
1189 return true
1190 })
1191
Neha Sharma96b7bf22020-06-15 10:37:32 +00001192 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001194 }
1195
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001196 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001197
1198 // check the ONU is already know to the OLT
1199 // NOTE the second time the ONU is discovered this should return a device
1200 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1201
1202 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001203 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 -08001204 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001205 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 -08001206 switch e.Code() {
1207 case codes.Internal:
1208 // this probably means NOT FOUND, so just create a new device
1209 onuDevice = nil
1210 case codes.DeadlineExceeded:
1211 // if the call times out, cleanup and exit
1212 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001213 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001214 }
1215 }
1216 }
1217
1218 if onuDevice == nil {
1219 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001220 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001221 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001222 ponintfid := onuDiscInd.GetIntfId()
npujarec5762e2020-01-01 14:08:48 +05301223 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001224
Neha Sharma96b7bf22020-06-15 10:37:32 +00001225 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001226
1227 if err != nil {
1228 // if we can't create an ID in resource manager,
1229 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001230 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001231 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001232 "pon-intf-id": ponintfid,
1233 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001234 }
1235
Neha Sharma8f4e4322020-08-06 10:51:53 +00001236 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001237 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001238 dh.discOnus.Delete(sn)
1239 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 +05301240 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001241 "pon-intf-id": ponintfid,
1242 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001243 }
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001244 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 -04001245 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"error": err})
1246 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001247 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301248 log.Fields{"onuDevice": onuDevice,
1249 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001250 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301251 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001252 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001253
1254 // we can now use the existing ONU Id
1255 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001256 //Insert the ONU into cache to use in OnuIndication.
1257 //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 +00001258 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001259 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301260 "intfId": onuDiscInd.GetIntfId(),
1261 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001262 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001263
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301264 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301265 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001266 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301267 log.Fields{"onu": onuDev,
1268 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001269
Kent Hagermane6ff1012020-07-14 15:07:53 -04001270 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301271 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001273 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001274 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001275 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001276 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301277 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001278 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001279 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001280 }
1281 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001282}
1283
Mahir Gunyelb0046752021-02-26 13:51:05 -08001284func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001285
1286 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001287 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001288 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001289 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001290 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001291 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301292 log.Fields{"onuId": onuInd.OnuId,
1293 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301294 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001295 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Mahir Gunyelb0046752021-02-26 13:51:05 -08001296 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301297
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 errFields := log.Fields{"device-id": dh.device.Id}
1299
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301300 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1301
Mahir Gunyele77977b2019-06-27 05:36:22 -07001302 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1303 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001304 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001305 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001306 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001307 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1308 if serialNumber != "" {
1309 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001311 } else {
1312 kwargs["onu_id"] = onuInd.OnuId
1313 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001314 errFields["onu-id"] = onuInd.OnuId
1315 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001316 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001317 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001318 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001319
David K. Bainbridge794735f2020-02-11 21:01:37 -08001320 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001321 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001322 }
1323
David K. Bainbridge794735f2020-02-11 21:01:37 -08001324 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001325 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 "previousIntfId": onuDevice.ParentPortNo,
1327 "currentIntfId": ponPort})
1328 }
1329
1330 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001331 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301332 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1333 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301334 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001335 }
1336 if !foundInCache {
1337 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1338
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301339 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 -08001340
1341 }
kesavand7cf3a052020-08-28 12:49:18 +05301342 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07001343 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().Unix()); err != nil {
kesavand7cf3a052020-08-28 12:49:18 +05301344 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"error": err})
1345 }
1346 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001347 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001348 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 }
1350 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001351}
1352
Neha Sharma96b7bf22020-06-15 10:37:32 +00001353func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001354 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 -07001355 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1356 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1357 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1358 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001359 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001360 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1361 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001362 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001363 onuInd.OperState = "down"
1364 }
1365 }
1366
David K. Bainbridge794735f2020-02-11 21:01:37 -08001367 switch onuInd.OperState {
1368 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001369 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 -07001370 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301371 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001372 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001373 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301374 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001375 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001376 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001377 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001378 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001379 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001380 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001381 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 -04001382 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301383 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001384 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001385 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301386 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001387 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001388 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001389 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001390 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001391 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001392 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001393 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001394 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001395 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001396}
1397
cuilin20187b2a8c32019-03-26 19:52:28 -07001398func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1399 if serialNum != nil {
1400 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001401 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001402 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001403}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001404func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1405 decodedStr, err := hex.DecodeString(serialNum[4:])
1406 if err != nil {
1407 return nil, err
1408 }
1409 return &oop.SerialNumber{
1410 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001411 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001412 }, nil
1413}
cuilin20187b2a8c32019-03-26 19:52:28 -07001414
1415func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
Mahir Gunyelb0046752021-02-26 13:51:05 -08001416 if len(vendorSpecific) > 3 {
1417 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
1418 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
1419 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1420 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1421 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1422 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1423 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1424 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1425 return tmp
1426 }
1427 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001428}
1429
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001430//UpdateFlowsBulk upates the bulk flow
1431func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301432 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001433}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001434
1435//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001436func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1437 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301438 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001439 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301440 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001441 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001442 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001443 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001444 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001445 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001446 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001447 "intf-id": parentPort,
1448 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001449 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001450 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 -08001451 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301452}
1453
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001454// SendPacketInToCore sends packet-in to core
1455// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1456// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001457func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001458 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001459 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001460 "port": logicalPort,
1461 "packet": hex.EncodeToString(packetPayload),
1462 "device-id": dh.device.Id,
1463 })
1464 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001465 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 +05301466 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001467 "source": "adapter",
1468 "destination": "core",
1469 "device-id": dh.device.Id,
1470 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001471 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001472 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001473 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001474 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001475 "packet": hex.EncodeToString(packetPayload),
1476 "device-id": dh.device.Id,
1477 })
1478 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001479 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001480}
1481
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001482// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001483func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001484 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001485
1486 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1487 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001488 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001489 }
1490
Kent Hagermane6ff1012020-07-14 15:07:53 -04001491 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001492 metrics := dh.metrics.GetSubscriberMetrics()
1493 for _, m := range pmConfigs.Metrics {
1494 metrics[m.Name].Enabled = m.Enabled
1495
1496 }
1497 }
1498}
1499
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001500//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301501func (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 +00001502 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 +01001503
Girish Gowdra491a9c62021-01-06 16:43:07 -08001504 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001505 var errorsList []error
1506
Girish Gowdru0c588b22019-04-23 23:24:56 -04001507 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001508 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001509 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001510
Neha Sharma96b7bf22020-06-15 10:37:32 +00001511 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301512 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001513 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301514 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001515 if flow_utils.HasGroup(flow) {
1516 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1517 } else {
1518 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1519 }
Girish Gowdracefae192020-03-19 18:14:10 -07001520 if err != nil {
1521 errorsList = append(errorsList, err)
1522 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001523 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301524
1525 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001526 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001527 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301528 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001529 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301530 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001531 if flow_utils.HasGroup(flow) {
1532 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1533 } else {
1534 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1535 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001536 if err != nil {
1537 errorsList = append(errorsList, err)
1538 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301539 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001540 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001541
Girish Gowdracefae192020-03-19 18:14:10 -07001542 // 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 +00001543 if groups != nil {
1544 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001545 // err = dh.groupMgr.AddGroup(ctx, group)
1546 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001547 if err != nil {
1548 errorsList = append(errorsList, err)
1549 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001550 }
1551 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001552 // err = dh.groupMgr.ModifyGroup(ctx, group)
1553 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001554 if err != nil {
1555 errorsList = append(errorsList, err)
1556 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001557 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001558 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001559 // err = dh.groupMgr.DeleteGroup(ctx, group)
1560 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001561 if err != nil {
1562 errorsList = append(errorsList, err)
1563 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001564 }
1565 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001566 if len(errorsList) > 0 {
1567 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1568 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001569 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001570 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301571}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001572
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001573//DisableDevice disables the given device
1574//It marks the following for the given device:
1575//Device-Handler Admin-State : down
1576//Device Port-State: UNKNOWN
1577//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001578func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001579 /* On device disable ,admin state update has to be done prior sending request to agent since
1580 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001581 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001582 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001583 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001584 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001585 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001586 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001587 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001588 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001589 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001590 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301591
1592 dh.discOnus = sync.Map{}
1593 dh.onus = sync.Map{}
1594
Thomas Lee S85f37312020-04-03 17:06:12 +05301595 //stopping the stats collector
1596 dh.stopCollector <- true
1597
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001599 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301600 //Update device Admin state
1601 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001602 // 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 +00001603 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 -04001604 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001605 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001606 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001607 return nil
1608}
1609
Neha Sharma96b7bf22020-06-15 10:37:32 +00001610func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001611 // Update onu state as unreachable in onu adapter
1612 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301613 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001614 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001615 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001616 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001617 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 -04001618 }
1619 if onuDevices != nil {
1620 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001621 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001622 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001623 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001625 "From Adapter": dh.openOLT.config.Topic, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001626 }
1627
1628 }
1629 }
1630
1631}
1632
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001633//ReenableDevice re-enables the olt device after disable
1634//It marks the following for the given device:
1635//Device-Handler Admin-State : up
1636//Device Port-State: ACTIVE
1637//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001638func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001639 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301640 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001641 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301642 }
1643 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001644 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001645
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001646 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001647
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001648 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1649 if err != nil {
divyadesai3af43e12020-08-18 07:10:54 +00001650 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001651 }
1652 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001653 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001654 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001655 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001656 device.OperStatus = voltha.OperStatus_ACTIVE
1657 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001658
Neha Sharma8f4e4322020-08-06 10:51:53 +00001659 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 +05301660 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001661 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001662 "connect-status": device.ConnectStatus,
1663 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001664 }
kesavand39e0aa32020-01-28 20:58:50 -05001665
Neha Sharma96b7bf22020-06-15 10:37:32 +00001666 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001667
1668 return nil
1669}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001670
npujarec5762e2020-01-01 14:08:48 +05301671func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001672 var uniID uint32
1673 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301674 for _, port := range onu.UniPorts {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001675 uniID = UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001676 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001677 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001678 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001679 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001680 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001681 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301682 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001683 for _, tpID := range tpIDList {
Girish Gowdraa482f272021-03-24 23:04:19 -07001684 if err = dh.resourceMgr.RemoveMeterInfoForOnu(ctx, "upstream", 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-upstream", 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-upstream", log.Fields{"onu-id": onu.OnuID})
Girish Gowdraa482f272021-03-24 23:04:19 -07001688 if err = dh.resourceMgr.RemoveMeterInfoForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001689 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001690 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001691 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301692 }
npujarec5762e2020-01-01 14:08:48 +05301693 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1694 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001695 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301696 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001697 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001698 if err = dh.resourceMgr.DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001699 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 +00001700 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001701 if err = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID)); err != nil {
1702 logger.Debugw(ctx, "failed-to-remove-flow-for", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
1703 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001704 }
1705 return nil
1706}
1707
npujarec5762e2020-01-01 14:08:48 +05301708func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001709 nniUniID := -1
1710 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301711
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001712 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301713 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001714 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001715 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301716 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301717 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001718 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001719 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001720 logger.Debugw(ctx, "nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301721 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301722 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001723 _ = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, nniIntfID, -1, -1)
1724
Devmalya Paul495b94a2019-08-27 19:42:00 -04001725 }
npujarec5762e2020-01-01 14:08:48 +05301726 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001727 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301728 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001729
David K. Bainbridge794735f2020-02-11 21:01:37 -08001730 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001731}
1732
1733// 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 +05301734func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001735 logger.Debug(ctx, "function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001736 /* Clear the KV store data associated with the all the UNI ports
1737 This clears up flow data and also resource map data for various
1738 other pon resources like alloc_id and gemport_id
1739 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001740 go dh.cleanupDeviceResources(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001741 logger.Debug(ctx, "removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001742 // Stop the Stats collector
1743 dh.stopCollector <- true
1744 // stop the heartbeat check routine
1745 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301746 dh.lockDevice.RLock()
1747 // Stop the read indication only if it the routine is active
1748 if dh.isReadIndicationRoutineActive {
1749 dh.stopIndications <- true
1750 }
1751 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001752 //Reset the state
1753 if dh.Client != nil {
1754 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301755 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001756 }
1757 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08001758 dh.removeOnuIndicationChannels(ctx)
Girish Gowdrab1caa442020-10-19 12:24:39 -07001759 // There is no need to update the core about operation status and connection status of the OLT.
1760 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1761 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1762 // because the device does not exist in DB.
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001763 return nil
1764}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001765func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001766
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001767 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301768 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001769 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301770 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301771 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301772 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001773 _ = olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001774 "device-id": dh.device.Id,
Kent Hagermane6ff1012020-07-14 15:07:53 -04001775 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301776 }
1777 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301778 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301780 if err = dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001781 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301782 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301783 // Clear flowids for gem cache.
1784 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301785 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301786 }
1787 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301788 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301789 }
npujarec5762e2020-01-01 14:08:48 +05301790 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301791 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301792 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301793 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001794 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001795 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001796 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001797 /* Clear the flows from KV store associated with NNI port.
1798 There are mostly trap rules from NNI port (like LLDP)
1799 */
npujarec5762e2020-01-01 14:08:48 +05301800 if err := dh.clearNNIData(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001801 logger.Errorw(ctx, "failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001802 }
A R Karthick1f85b802019-10-11 05:06:05 +00001803
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001804 /* Clear the resource pool for each PON port in the background */
Kent Hagermane6ff1012020-07-14 15:07:53 -04001805 go func() {
1806 if err := dh.resourceMgr.Delete(ctx); err != nil {
1807 logger.Debug(ctx, err)
1808 }
1809 }()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001810 }
A R Karthick1f85b802019-10-11 05:06:05 +00001811
Devmalya Paul495b94a2019-08-27 19:42:00 -04001812 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301813 dh.onus.Range(func(key interface{}, value interface{}) bool {
1814 dh.onus.Delete(key)
1815 return true
1816 })
1817
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001818 /*Delete discovered ONU map for the device*/
1819 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1820 dh.discOnus.Delete(key)
1821 return true
1822 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001823}
1824
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001825//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001826func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001827 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301828 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001829 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001831 return nil
1832}
1833
David K. Bainbridge794735f2020-02-11 21:01:37 -08001834func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001835 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001836 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001837 "packet-indication": *packetIn,
1838 "device-id": dh.device.Id,
1839 "packet": hex.EncodeToString(packetIn.Pkt),
1840 })
1841 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001842 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001843 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001844 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001845 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001846 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001847 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001848 "logical-port-num": logicalPortNum,
1849 "device-id": dh.device.Id,
1850 "packet": hex.EncodeToString(packetIn.Pkt),
1851 })
1852 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001853
Neha Sharma8f4e4322020-08-06 10:51:53 +00001854 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 +05301855 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001856 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301857 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001858 "device-id": dh.device.Id,
1859 "packet": hex.EncodeToString(packetIn.Pkt),
1860 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001861 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001862
Matteo Scandolo92186242020-06-12 10:54:18 -07001863 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001864 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001865 "packet": hex.EncodeToString(packetIn.Pkt),
1866 "device-id": dh.device.Id,
1867 })
1868 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001869 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001870}
1871
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001872// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301873func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001874 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001876 "device-id": dh.device.Id,
1877 "egress-port-no": egressPortNo,
1878 "pkt-length": len(packet.Data),
1879 "packet": hex.EncodeToString(packet.Data),
1880 })
1881 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001882
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001883 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001884 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001885 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1886 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301887 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1888 // Do not packet-out lldp packets on uni port.
1889 // ONOS has no clue about uni/nni ports, it just packets out on all
1890 // available ports on the Logical Switch. It should not be interested
1891 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001892 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001893 "device-id": dh.device.Id,
1894 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301895 return nil
1896 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001897 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1898 if innerEthType == 0x8100 {
1899 // q-in-q 802.1ad or 802.1q double tagged packet.
1900 // slice out the outer tag.
1901 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001902 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001903 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001904 "packet-data": hex.EncodeToString(packet.Data),
1905 "device-id": dh.device.Id,
1906 })
1907 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001908 }
1909 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001910 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1911 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001912 uniID := UniIDFromPortNum(uint32(egressPortNo))
1913
Girish Gowdra9602eb42020-09-09 15:50:39 -07001914 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001915 if err != nil {
1916 // In this case the openolt agent will receive the gemPortID as 0.
1917 // The agent tries to retrieve the gemPortID in this case.
1918 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001919 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001920 "intf-id": intfID,
1921 "onu-id": onuID,
1922 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001923 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301924 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001925 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001926 }
1927
1928 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07001929 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001930 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001931 "egress-port-no": egressPortNo,
1932 "intf-id": intfID,
1933 "onu-id": onuID,
1934 "uni-id": uniID,
1935 "gem-port-id": gemPortID,
1936 "packet": hex.EncodeToString(packet.Data),
1937 "device-id": dh.device.Id,
1938 })
1939 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001940
npujarec5762e2020-01-01 14:08:48 +05301941 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301942 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001943 "source": "adapter",
1944 "destination": "onu",
1945 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001946 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001947 "oni-id": onuID,
1948 "uni-id": uniID,
1949 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001950 "packet": hex.EncodeToString(packet.Data),
1951 "device-id": dh.device.Id,
1952 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001953 }
1954 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001955 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001956 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001957 return olterrors.NewErrInvalidValue(log.Fields{
1958 "egress-nni-port": egressPortNo,
1959 "device-id": dh.device.Id,
1960 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001961 }
1962 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001963
Matteo Scandolo92186242020-06-12 10:54:18 -07001964 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001965 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001966 "uplink-pkt": uplinkPkt,
1967 "packet": hex.EncodeToString(packet.Data),
1968 "device-id": dh.device.Id,
1969 })
1970 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001971
npujarec5762e2020-01-01 14:08:48 +05301972 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001973 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1974 "packet": hex.EncodeToString(packet.Data),
1975 "device-id": dh.device.Id,
1976 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001977 }
1978 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001979 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301980 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001981 "egressPortType": egressPortType,
1982 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301983 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001984 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001985 }
1986 return nil
1987}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001988
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001989func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1990 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001991}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301992
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001993func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001994
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301995 // start the heartbeat check towards the OLT.
1996 var timerCheck *time.Timer
1997
1998 for {
1999 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
2000 select {
2001 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00002002 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002003 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002004 logger.Warnw(ctx, "heartbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302005 if timerCheck == nil {
2006 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002007 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302008 }
2009 } else {
2010 if timerCheck != nil {
2011 if timerCheck.Stop() {
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002012 logger.Debugw(ctx, "got-heartbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302013 }
2014 timerCheck = nil
2015 }
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002016 logger.Debugw(ctx, "heartbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05302017 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05302018 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302019 }
2020 cancel()
2021 case <-dh.stopHeartbeatCheck:
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002022 logger.Debugw(ctx, "stopping-heartbeat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302023 return
2024 }
2025 }
2026}
2027
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002028func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
2029 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
2030 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002031 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2032 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2033 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2034 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2035 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002036 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002037 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2038 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002039 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302040
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002041 logger.Debugw(ctx, "update-state-unreachable", log.Fields{"device-id": dh.device.Id, "connect-status": device.ConnectStatus,
2042 "admin-state": device.AdminState, "oper-status": device.OperStatus})
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002043 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
2044 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002045 _ = 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 -04002046 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002047 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002048 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002049 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002050
2051 //raise olt communication failure event
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -07002052 raisedTs := time.Now().Unix()
Gamze Abaka07868a52020-12-17 14:19:28 +00002053 device.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2054 device.OperStatus = voltha.OperStatus_UNKNOWN
2055 go dh.eventMgr.oltCommunicationEvent(ctx, device, raisedTs)
2056
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002057 go dh.cleanupDeviceResources(ctx)
Matteo Scandolo861e06e2021-05-26 11:51:46 -07002058 // Stop the Stats collector
2059 dh.stopCollector <- true
2060 // stop the heartbeat check routine
2061 dh.stopHeartbeatCheck <- true
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002062
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002063 dh.lockDevice.RLock()
2064 // Stop the read indication only if it the routine is active
2065 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2066 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2067 // on next execution of the readIndication routine.
2068 if dh.isReadIndicationRoutineActive {
2069 dh.stopIndications <- true
2070 }
2071 dh.lockDevice.RUnlock()
2072
Gamze Abakac2c32a62021-03-11 11:44:18 +00002073 //reset adapter reconcile flag
2074 dh.adapterPreviouslyConnected = false
2075
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002076 dh.transitionMap.Handle(ctx, DeviceInit)
2077
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302078 }
2079}
kesavand39e0aa32020-01-28 20:58:50 -05002080
2081// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002082func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2083 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2084 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002085}
2086
2087// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002088func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2089 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2090 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002091}
2092
kdarapu1afeceb2020-02-12 01:38:09 -05002093//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 +00002094func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2095 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002096 if port.GetType() == voltha.Port_ETHERNET_NNI {
2097 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002098 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302099 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302100 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002101 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002102 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002103 }
2104 // fetch interfaceid from PortNo
2105 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2106 ponIntf := &oop.Interface{IntfId: ponID}
2107 var operStatus voltha.OperStatus_Types
2108 if enablePort {
2109 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302110 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002111
2112 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302113 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002114 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002115 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002116 }
2117 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002118 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002119 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002120 } else {
2121 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302122 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002123 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302124 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002125 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002126 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002127 }
2128 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002129 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002130 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002131 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302132 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 +05302133 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302134 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002135 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002136 }
2137 return nil
2138}
2139
kdarapu1afeceb2020-02-12 01:38:09 -05002140//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002141func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002142 // Disable the port and update the oper_port_status to core
2143 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002144 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002145 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002146 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302147 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302148 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002149 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002150 }
2151 }
2152 }
2153 return nil
2154}
2155
2156//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002157func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2158 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2159 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002160 if port.Type == voltha.Port_ETHERNET_NNI {
2161 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002162 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002163 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002164 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002165 }
2166 }
2167 if port.Type == voltha.Port_PON_OLT {
2168 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002169 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002170 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002171 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002172 }
2173 }
2174 }
2175}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002176
2177// ChildDeviceLost deletes ONU and clears pon resources related to it.
Girish Gowdraa0870562021-03-11 14:30:14 -08002178func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32, onuSn string) error {
divyadesai3af43e12020-08-18 07:10:54 +00002179 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002180 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2181 onuKey := dh.formOnuKey(intfID, onuID)
Girish Gowdraa0870562021-03-11 14:30:14 -08002182
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002183 var sn *oop.SerialNumber
2184 var err error
Girish Gowdraa0870562021-03-11 14:30:14 -08002185 if sn, err = dh.deStringifySerialNumber(onuSn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302186 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002187 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302188 "devicer-id": dh.device.Id,
Girish Gowdraa0870562021-03-11 14:30:14 -08002189 "serial-number": onuSn}, err).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002190 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002191
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002192 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Neha Sharma8f4e4322020-08-06 10:51:53 +00002193 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302194 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302195 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002196 "onu-id": onuID}, err).Log()
2197 }
2198 //clear PON resources associated with ONU
2199 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002200 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002201 logger.Warnw(ctx, "failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002202 "device-id": dh.device.Id,
2203 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002204 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002205 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002206 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002207 "device-id": dh.device.Id,
2208 "intf-id": intfID,
2209 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002210 } else {
2211 for i, onu := range onuGemData {
Girish Gowdraa0870562021-03-11 14:30:14 -08002212 if onu.OnuID == onuID && onu.SerialNumber == onuSn {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002213 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002214 if err := dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002215 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302216 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002217 "onu-device": onu,
2218 "error": err})
2219 }
2220 // Clear flowids for gem cache.
2221 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002222 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002223 }
2224 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002225 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002226 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002227 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002228 "intf-id": intfID,
2229 "onu-device": onu,
2230 "onu-gem": onuGemData,
2231 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002232 //Not returning error on cleanup.
2233 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002234 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002235 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002236 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002237 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002238 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002239 }
2240 }
2241 dh.onus.Delete(onuKey)
Girish Gowdraa0870562021-03-11 14:30:14 -08002242 dh.discOnus.Delete(onuSn)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002243 return nil
2244}
Girish Gowdracefae192020-03-19 18:14:10 -07002245
2246func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002247 for _, field := range flow_utils.GetOfbFields(flow) {
2248 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002249 return field.GetPort()
2250 }
2251 }
2252 return InvalidPort
2253}
2254
2255func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002256 for _, action := range flow_utils.GetActions(flow) {
2257 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002258 if out := action.GetOutput(); out != nil {
2259 return out.GetPort()
2260 }
2261 }
2262 }
2263 return InvalidPort
2264}
2265
Girish Gowdracefae192020-03-19 18:14:10 -07002266func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2267 inPort := getInPortFromFlow(flow)
2268 outPort := getOutPortFromFlow(flow)
2269
2270 if inPort == InvalidPort || outPort == InvalidPort {
2271 return inPort, outPort
2272 }
2273
2274 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2275 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2276 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002277 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002278 return uniPort, outPort
2279 }
2280 }
2281 } else {
2282 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2283 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002284 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002285 return inPort, uniPort
2286 }
2287 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2288 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002289 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002290 return uniPort, outPort
2291 }
2292 }
2293 }
2294
2295 return InvalidPort, InvalidPort
2296}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002297
2298func extractOmciTransactionID(omciPkt []byte) uint16 {
2299 if len(omciPkt) > 3 {
2300 d := omciPkt[0:2]
2301 transid := binary.BigEndian.Uint16(d)
2302 return transid
2303 }
2304 return 0
2305}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002306
2307// StoreOnuDevice stores the onu parameters to the local cache.
2308func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2309 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2310 dh.onus.Store(onuKey, onuDevice)
2311}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002312
Neha Sharma8f4e4322020-08-06 10:51:53 +00002313func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002314 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002315 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002316 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002317 resp := new(voltha.ReturnValues)
2318 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002319 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002320 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002321 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2322 return nil, err
2323 }
2324 ID = device.ProxyAddress.GetOnuId()
2325 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2326 valueparam.Onu = &Onu
2327 valueparam.Value = value
2328
2329 // This API is unsupported until agent patch is added
2330 resp.Unsupported = uint32(value)
2331 _ = ctx
2332
2333 // Uncomment this code once agent changes are complete and tests
2334 /*
2335 resp, err = dh.Client.GetValue(ctx, valueparam)
2336 if err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002337 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002338 return nil, err
2339 }
2340 */
2341
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002342 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 -08002343 return resp, nil
2344}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002345
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002346func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002347 // Default to PON0
2348 var intfID uint32
2349 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002350 if inPort != InvalidPort && outPort != InvalidPort {
2351 _, intfID, _, _ = ExtractAccessFromFlow(inPort, outPort)
2352 }
2353 return intfID
2354}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002355
Mahir Gunyelb0046752021-02-26 13:51:05 -08002356func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, intfID uint32) chan onuIndicationMsg {
2357 dh.perPonOnuIndicationChannelLock.Lock()
2358 if ch, ok := dh.perPonOnuIndicationChannel[intfID]; ok {
2359 dh.perPonOnuIndicationChannelLock.Unlock()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002360 return ch.indicationChannel
2361 }
2362 channels := onuIndicationChannels{
2363 //We create a buffered channel here to avoid calling function to be blocked
Mahir Gunyelb0046752021-02-26 13:51:05 -08002364 //in case of multiple indications from the ONUs,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002365 //especially in the case where indications are buffered in OLT.
Mahir Gunyelb0046752021-02-26 13:51:05 -08002366 indicationChannel: make(chan onuIndicationMsg, 500),
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002367 stopChannel: make(chan struct{}),
2368 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002369 dh.perPonOnuIndicationChannel[intfID] = channels
2370 dh.perPonOnuIndicationChannelLock.Unlock()
2371 go dh.onuIndicationsRoutine(&channels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002372 return channels.indicationChannel
2373
2374}
2375
Mahir Gunyelb0046752021-02-26 13:51:05 -08002376func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context) {
2377 logger.Debug(ctx, "remove-onu-indication-channels", log.Fields{"device-id": dh.device.Id})
2378 dh.perPonOnuIndicationChannelLock.Lock()
2379 defer dh.perPonOnuIndicationChannelLock.Unlock()
2380 for _, v := range dh.perPonOnuIndicationChannel {
2381 close(v.stopChannel)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002382 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002383 dh.perPonOnuIndicationChannel = make(map[uint32]onuIndicationChannels)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002384}
2385
Mahir Gunyelb0046752021-02-26 13:51:05 -08002386func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, intfID uint32) {
2387 ind := onuIndicationMsg{
2388 ctx: ctx,
2389 indication: indication,
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002390 }
Mahir Gunyelb0046752021-02-26 13:51:05 -08002391 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "intfID": intfID})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002392 // Send the onuIndication on the ONU channel
Mahir Gunyelb0046752021-02-26 13:51:05 -08002393 dh.getOnuIndicationChannel(ctx, intfID) <- ind
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002394}
2395
Mahir Gunyelb0046752021-02-26 13:51:05 -08002396func (dh *DeviceHandler) onuIndicationsRoutine(onuChannels *onuIndicationChannels) {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002397 for {
2398 select {
2399 // process one indication per onu, before proceeding to the next one
2400 case onuInd := <-onuChannels.indicationChannel:
2401 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
Mahir Gunyelb0046752021-02-26 13:51:05 -08002402 "ind": onuInd.indication})
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002403 switch onuInd.indication.Data.(type) {
2404 case *oop.Indication_OnuInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002405 if err := dh.onuIndication(onuInd.ctx, onuInd.indication.GetOnuInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002406 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2407 "type": "onu-indication",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002408 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002409 }
2410 case *oop.Indication_OnuDiscInd:
Mahir Gunyelb0046752021-02-26 13:51:05 -08002411 if err := dh.onuDiscIndication(onuInd.ctx, onuInd.indication.GetOnuDiscInd()); err != nil {
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002412 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2413 "type": "onu-discovery",
Mahir Gunyelb0046752021-02-26 13:51:05 -08002414 "device-id": dh.device.Id}, err).Log()
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002415 }
2416 }
2417 case <-onuChannels.stopChannel:
2418 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2419 close(onuChannels.indicationChannel)
2420 return
2421 }
2422 }
2423}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002424
2425// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2426// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
2427func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *voltha.OfpFlowStats, group *voltha.OfpGroupEntry, action string) error {
2428 // Step1 : Fill McastFlowOrGroupControlBlock
2429 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2430 // Step3 : Wait on response channel for response
2431 // Step4 : Return error value
2432 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2433 errChan := make(chan error)
2434 var groupID uint32
2435 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2436 ctx: ctx,
2437 flowOrGroupAction: action,
2438 flow: flow,
2439 group: group,
2440 errChan: &errChan,
2441 }
2442 if flow != nil {
2443 groupID = flow_utils.GetGroup(flow)
2444 } else if group != nil {
2445 groupID = group.Desc.GroupId
2446 } else {
2447 return errors.New("flow-and-group-both-nil")
2448 }
2449 // Derive the appropriate go routine to handle the request by a simple module operation.
2450 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2451 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2452 // Wait for handler to return error value
2453 err := <-errChan
2454 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"flow": flow, "group": group, "action": action, "err": err})
2455 return err
2456}
2457
2458// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
2459func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock) {
2460 for {
2461 // block on the channel to receive an incoming mcast flow/group
2462 // process the flow completely before proceeding to handle the next flow
2463 mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel
2464 if mcastFlowOrGroupCb.flow != nil {
2465 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2466 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2467 log.Fields{"device-id": dh.device.Id,
2468 "flowToAdd": mcastFlowOrGroupCb.flow})
2469 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2470 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2471 // Pass the return value over the return channel
2472 *mcastFlowOrGroupCb.errChan <- err
2473 } else { // flow remove
2474 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2475 log.Fields{"device-id": dh.device.Id,
2476 "flowToRemove": mcastFlowOrGroupCb.flow})
2477 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2478 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2479 // Pass the return value over the return channel
2480 *mcastFlowOrGroupCb.errChan <- err
2481 }
2482 } else { // mcast group
2483 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2484 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2485 log.Fields{"device-id": dh.device.Id,
2486 "groupToAdd": mcastFlowOrGroupCb.group})
2487 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2488 // Pass the return value over the return channel
2489 *mcastFlowOrGroupCb.errChan <- err
2490 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2491 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2492 log.Fields{"device-id": dh.device.Id,
2493 "groupToModify": mcastFlowOrGroupCb.group})
2494 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2495 // Pass the return value over the return channel
2496 *mcastFlowOrGroupCb.errChan <- err
2497 } else { // group remove
2498 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2499 log.Fields{"device-id": dh.device.Id,
2500 "groupToRemove": mcastFlowOrGroupCb.group})
2501 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2502 // Pass the return value over the return channel
2503 *mcastFlowOrGroupCb.errChan <- err
2504 }
2505 }
2506 }
2507}
kesavand62126212021-01-12 04:56:06 -05002508
2509func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2510
2511 singleValResp := extension.SingleGetValueResponse{
2512 Response: &extension.GetValueResponse{
2513 Response: &extension.GetValueResponse_PortCoutners{
2514 PortCoutners: &extension.GetOltPortCountersResponse{},
2515 },
2516 },
2517 }
2518
2519 errResp := func(status extension.GetValueResponse_Status,
2520 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2521 return &extension.SingleGetValueResponse{
2522 Response: &extension.GetValueResponse{
2523 Status: status,
2524 ErrReason: reason,
2525 },
2526 }
2527 }
2528
2529 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2530 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2531 //send error response
2532 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2533 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2534 }
2535 statIndChn := make(chan bool, 1)
2536 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2537 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2538 //request openOlt agent to send the the port statistics indication
2539
2540 go func() {
2541 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2542 if err != nil {
2543 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2544 }
2545 }()
2546 select {
2547 case <-statIndChn:
2548 //indication received for ports stats
2549 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2550 case <-time.After(oltPortInfoTimeout * time.Second):
2551 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2552 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2553 case <-ctx.Done():
2554 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2555 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2556 }
2557 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2558 //get nni stats
2559 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
2560 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2561 cmnni := dh.portStats.collectNNIMetrics(intfID)
2562 if cmnni == nil {
2563 //TODO define the error reason
2564 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2565 }
2566 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2567 return &singleValResp
2568
2569 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2570 // get pon stats
2571 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
2572 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2573 cmpon := dh.portStats.collectPONMetrics(intfID)
2574 if cmpon == nil {
2575 //TODO define the error reason
2576 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2577 }
2578 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2579 return &singleValResp
2580 }
2581 }
2582 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2583}