blob: 8eaf0bf59950bc506a72516b50b1b8d3793fcaf1 [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 Gunyel2fb81472020-12-16 23:18:34 -080097 totalPonPorts uint32
98 perOnuChannel map[string]onuIndicationChannels
99 perOnuChannelLock sync.Mutex
Girish Gowdra491a9c62021-01-06 16:43:07 -0800100
101 // Slice of channels. Each channel in slice, index by (mcast-group-id modulo MaxNumOfGroupHandlerChannels)
102 // A go routine per index, waits on a unique channel for incoming mcast flow or group (add/modify/remove).
103 incomingMcastFlowOrGroup []chan McastFlowOrGroupControlBlock
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700104}
105
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700106//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109 deviceType string
110 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 onuID uint32
112 intfID uint32
113 proxyDeviceID string
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530114 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400115 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700116}
117
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800118type perOnuIndication struct {
119 ctx context.Context
120 indication *oop.Indication
121 serialNumber string
122}
123
124type onuIndicationChannels struct {
125 indicationChannel chan perOnuIndication
126 stopChannel chan struct{}
127}
128
Girish Gowdra491a9c62021-01-06 16:43:07 -0800129//McastFlowOrGroupControlBlock is created per mcast flow/group add/modify/remove and pushed on the incomingMcastFlowOrGroup channel slice
130//The McastFlowOrGroupControlBlock is then picked by the mcastFlowOrGroupChannelHandlerRoutine for further processing.
131//There are MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine routines which monitor for any incoming mcast flow/group messages
132//and process them serially. The mcast flow/group are assigned these routines based on formula (group-id modulo MaxNumOfGroupHandlerChannels)
133type McastFlowOrGroupControlBlock struct {
134 ctx context.Context // Flow/group handler context
135 flowOrGroupAction string // one of McastFlowOrGroupAdd, McastFlowOrGroupModify or McastFlowOrGroupDelete
136 flow *voltha.OfpFlowStats // Flow message (can be nil or valid flow)
137 group *voltha.OfpGroupEntry // Group message (can be nil or valid group)
138 errChan *chan error // channel to report the mcast Flow/group handling error
139}
140
Naga Manjunath7615e552019-10-11 22:35:47 +0530141var pmNames = []string{
142 "rx_bytes",
143 "rx_packets",
144 "rx_mcast_packets",
145 "rx_bcast_packets",
146 "tx_bytes",
147 "tx_packets",
148 "tx_mcast_packets",
149 "tx_bcast_packets",
150}
151
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700152//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530153func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700154 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700155 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700156 device.deviceType = deviceTp
157 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700158 device.onuID = onuID
159 device.intfID = intfID
160 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530161 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700162 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530163}
164
165//NewDeviceHandler creates a new device handler
Himani Chawlacd407802020-12-10 12:08:59 +0530166func 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 -0700167 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800168 dh.cm = cm
cuilin20187b2a8c32019-03-26 19:52:28 -0700169 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400170 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400171 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700172 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700173 dh.device = cloned
174 dh.openOLT = adapter
175 dh.exitChannel = make(chan int, 1)
176 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530177 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530178 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530179 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 -0500180 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400181 dh.stopIndications = make(chan bool, 1)
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800182 dh.perOnuChannel = make(map[string]onuIndicationChannels)
Girish Gowdra491a9c62021-01-06 16:43:07 -0800183 // Create a slice of buffered channels for handling concurrent mcast flow/group.
184 dh.incomingMcastFlowOrGroup = make([]chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
185 for i := range dh.incomingMcastFlowOrGroup {
186 dh.incomingMcastFlowOrGroup[i] = make(chan McastFlowOrGroupControlBlock, MaxNumOfGroupHandlerChannels)
187 // Spin up a go routine to handling incoming mcast flow/group (add/modify/remove).
188 // There will be MaxNumOfGroupHandlerChannels number of mcastFlowOrGroupChannelHandlerRoutine go routines.
189 // These routines will be blocked on the dh.incomingMcastFlowOrGroup[mcast-group-id modulo MaxNumOfGroupHandlerChannels] channel
190 // for incoming mcast flow/group to be processed serially.
191 go dh.mcastFlowOrGroupChannelHandlerRoutine(dh.incomingMcastFlowOrGroup[i])
192 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700193 //TODO initialize the support classes.
194 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530195}
196
197// start save the device to the data model
198func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700199 dh.lockDevice.Lock()
200 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000201 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700202 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000203 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530204}
205
206// stop stops the device dh. Not much to do for now
207func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700208 dh.lockDevice.Lock()
209 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000210 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700211 dh.exitChannel <- 1
Neha Sharma96b7bf22020-06-15 10:37:32 +0000212 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530213}
214
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400215func macifyIP(ip net.IP) string {
216 if len(ip) > 0 {
217 oct1 := strconv.FormatInt(int64(ip[12]), 16)
218 oct2 := strconv.FormatInt(int64(ip[13]), 16)
219 oct3 := strconv.FormatInt(int64(ip[14]), 16)
220 oct4 := strconv.FormatInt(int64(ip[15]), 16)
221 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
222 }
223 return ""
224}
225
Neha Sharma96b7bf22020-06-15 10:37:32 +0000226func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400227 var genmac string
228 var addr net.IP
229 var ips []string
230 var err error
231
Neha Sharma96b7bf22020-06-15 10:37:32 +0000232 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400233
234 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000235 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400236
237 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000238 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400239 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000240 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400241 }
242 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000243 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530244 log.Fields{"host": ips[0],
245 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400246 return genmac, nil
247 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000248 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400249 }
250
251 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000252 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530253 log.Fields{"host": host,
254 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400255 return genmac, nil
256}
257
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530258func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700259 slist := strings.Split(mac, ":")
260 result := make([]uint32, len(slist))
261 var err error
262 var tmp int64
263 for index, val := range slist {
264 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
265 return []uint32{1, 2, 3, 4, 5, 6}
266 }
267 result[index] = uint32(tmp)
268 }
269 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530270}
271
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272//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 -0800273func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530274
David K. Bainbridge794735f2020-02-11 21:01:37 -0800275 switch portType {
276 case voltha.Port_ETHERNET_NNI:
277 return fmt.Sprintf("nni-%d", portNum), nil
278 case voltha.Port_PON_OLT:
279 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700280 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800281
Girish Kumarf26e4882020-03-05 06:49:10 +0000282 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530283}
284
Neha Sharma96b7bf22020-06-15 10:37:32 +0000285func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000286 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700287 if state == "up" {
288 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500289 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500290 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700291 } else {
292 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500293 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700294 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700295 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400296 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800297 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000298 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400299 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500300
Neha Sharma8f4e4322020-08-06 10:51:53 +0000301 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 +0000302 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
Neha Sharma8f4e4322020-08-06 10:51:53 +0000303 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 -0400304 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
305 "device-id": dh.device.Id,
306 "port-type": portType,
307 "port-number": portNum,
308 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500309 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400310 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500311 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400312 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700313 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400314 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700315 PortNo: portNum,
316 Label: label,
317 Type: portType,
318 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700319 OfpPort: &of.OfpPort{
320 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
321 Config: 0,
322 State: uint32(of.OfpPortState_OFPPS_LIVE),
323 Curr: capacity,
324 Advertised: capacity,
325 Peer: capacity,
326 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
327 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
328 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700329 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000330 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700331 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000332 if err := dh.coreProxy.PortCreated(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000333 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800334 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000335 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400336 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000337 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530338 return nil
339}
340
Kent Hagermane6ff1012020-07-14 15:07:53 -0400341func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +0000342 device, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530343 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400344 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
345 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530346 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800347 dh.lockDevice.Lock()
348 defer dh.lockDevice.Unlock()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530349 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530350}
351
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700352// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530353// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800354func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700356 defer func() {
357 dh.lockDevice.Lock()
358 dh.isReadIndicationRoutineActive = false
359 dh.lockDevice.Unlock()
360 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700361 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700362 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700363 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700364 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400365 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530366 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400367 if err != nil || device == nil {
368 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000369 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400370 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400371
David Bainbridgef5879ca2019-12-13 21:17:54 +0000372 // Create an exponential backoff around re-enabling indications. The
373 // maximum elapsed time for the back off is set to 0 so that we will
374 // continue to retry. The max interval defaults to 1m, but is set
375 // here for code clarity
376 indicationBackoff := backoff.NewExponentialBackOff()
377 indicationBackoff.MaxElapsedTime = 0
378 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700379
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700380 dh.lockDevice.Lock()
381 dh.isReadIndicationRoutineActive = true
382 dh.lockDevice.Unlock()
383
Girish Gowdra3f974912020-03-23 20:35:18 -0700384Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700385 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400386 select {
387 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000388 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700389 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400390 default:
391 indication, err := indications.Recv()
392 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000393 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530394 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530395 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400396 // Use an exponential back off to prevent getting into a tight loop
397 duration := indicationBackoff.NextBackOff()
398 if duration == backoff.Stop {
399 // If we reach a maximum then warn and reset the backoff
400 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000401 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530402 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530403 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400404 indicationBackoff.Reset()
405 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700406
407 // On failure process a backoff timer while watching for stopIndications
408 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700409 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700410 select {
411 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000412 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700413 if !backoffTimer.Stop() {
414 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700415 }
416 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700417 case <-backoffTimer.C:
418 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700419 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700420 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
421 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400422 }
423 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000424 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530425 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000426 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530427 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530428 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700429 // Close the stream, and re-initialize it
430 if err = indications.CloseSend(); err != nil {
431 // Ok to ignore here, because we landed here due to a problem on the stream
432 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000433 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530434 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530435 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700436 }
437 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
438 return err
439 }
440 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400441 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530442 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400443 // Reset backoff if we have a successful receive
444 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400445 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530446 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000447 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530448 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530449 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400450 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400451 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400452 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700453 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700454 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700455 // Close the send stream
456 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700457
Girish Gowdra3f974912020-03-23 20:35:18 -0700458 return nil
459}
460
461func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
462
463 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
464 if err != nil {
465 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
466 }
467 if indications == nil {
468 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
469 }
470
471 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400472}
473
474// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
475func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
476 switch indication.Data.(type) {
477 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
478 return true
479
480 default:
481 return false
482 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700483}
484
David K. Bainbridge794735f2020-02-11 21:01:37 -0800485func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000486 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000487 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530488 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700489 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530490 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700491 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000492 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000493 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530494 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000495 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800496 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000497 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800498 }
499 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700500}
501
David K. Bainbridge794735f2020-02-11 21:01:37 -0800502// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530503func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400504 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700505 switch indication.Data.(type) {
506 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000507 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
508 defer span.Finish()
509
David K. Bainbridge794735f2020-02-11 21:01:37 -0800510 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400511 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800512 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700513 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000514 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
515 defer span.Finish()
516
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700517 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800518 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000519 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400520 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800521 }
522 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000523 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700524 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000525 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
526 defer span.Finish()
527
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700528 intfOperInd := indication.GetIntfOperInd()
529 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800530 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000531 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400532 _ = 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 -0800533 }
534 }()
Kent Hagermane6ff1012020-07-14 15:07:53 -0400535 if err := dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId()); err != nil {
536 logger.Warn(ctx, err)
537 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700538 } else if intfOperInd.GetType() == "pon" {
539 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
540 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800541 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000542 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400543 _ = 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 -0800544 }
545 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000546 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700547 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000548 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530549 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530550 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700551 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000552 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
553 defer span.Finish()
554
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000556 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700557 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800558 //put message to channel and return immediately
559 dh.putOnuIndicationToChannel(ctx, indication, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700560 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000561 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
562 defer span.Finish()
563
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700564 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000565 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800566 sn := dh.stringifySerialNumber(onuInd.SerialNumber)
567 //put message to channel and return immediately
568 dh.putOnuIndicationToChannel(ctx, indication, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700569 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000570 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
571 defer span.Finish()
572
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700573 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000574 logger.Debugw(ctx, "received-omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800575 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000576 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400577 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800578 }
579 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700580 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000581 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
582 defer span.Finish()
583
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700584 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000585 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700586 "intf-type": pktInd.IntfId,
587 "intf-id": pktInd.IntfId,
588 "gem-port-id": pktInd.GemportId,
589 "port-no": pktInd.PortNo,
590 "device-id": dh.device.Id,
591 })
592
593 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000594 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700595 "intf-type": pktInd.IntfId,
596 "intf-id": pktInd.IntfId,
597 "gem-port-id": pktInd.GemportId,
598 "port-no": pktInd.PortNo,
599 "packet": hex.EncodeToString(pktInd.Pkt),
600 "device-id": dh.device.Id,
601 })
602 }
603
David K. Bainbridge794735f2020-02-11 21:01:37 -0800604 go func() {
605 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400606 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800607 }
608 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000610 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
611 defer span.Finish()
612
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700613 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700614 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700615 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000616 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
617 defer span.Finish()
618
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700619 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000620 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700621 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000622 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
623 defer span.Finish()
624
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700625 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000626 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
627 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700628 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530629}
630
631// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530632func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530633 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000634 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530635
Girish Gowdru0c588b22019-04-23 23:24:56 -0400636 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530637 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400638 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000639 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400640 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000641
642 //Clear olt communication failure event
643 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
644 dh.device.OperStatus = voltha.OperStatus_ACTIVE
645 raisedTs := time.Now().UnixNano()
646 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
647
Girish Gowdru0c588b22019-04-23 23:24:56 -0400648 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530649}
650
651// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530652func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000653 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400654
npujarec5762e2020-01-01 14:08:48 +0530655 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400656 if err != nil || device == nil {
657 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000658 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400659 }
660
661 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400662
663 //Update the device oper state and connection status
664 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800665 dh.lockDevice.Lock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400666 dh.device = cloned
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800667 dh.lockDevice.Unlock()
Girish Gowdrud4245152019-05-10 00:47:31 -0400668
David K. Bainbridge794735f2020-02-11 21:01:37 -0800669 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000670 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400671 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400672
673 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530674 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400675 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000676 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400677 }
678 for _, onuDevice := range onuDevices.Items {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400679 // Update onu state as down in onu adapter
680 onuInd := oop.OnuIndication{}
681 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800682 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +0300683 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800684 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400685 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +0300686 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800687 "onu-indicator": onuInd,
688 "device-type": onuDevice.Type,
689 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700690 //Do not return here and continue to process other ONUs
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800691 } else {
692 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 -0700693 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400694 }
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800695 dh.lockDevice.Lock()
serkant.uluderya245caba2019-09-24 23:15:29 -0700696 /* Discovered ONUs entries need to be cleared , since after OLT
697 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530698 dh.discOnus = sync.Map{}
Girish Gowdrabe811ff2021-01-26 17:12:12 -0800699 dh.lockDevice.Unlock()
700
Neha Sharma96b7bf22020-06-15 10:37:32 +0000701 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700702 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530703}
704
705// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530706func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400707 var err error
Girish Kumar93e91742020-07-27 16:43:19 +0000708 // Use Intercepters to automatically inject and publish Open Tracing Spans by this GRPC client
709 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
710 grpc.WithInsecure(),
711 grpc.WithBlock(),
712 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000713 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000714 )),
715 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000716 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000717 )))
718
719 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530720 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530721 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000722 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400723 }
724 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530725}
726
727// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530728func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400729 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530730 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400731 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530732}
733
734// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530735func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530736 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000737 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400738
739 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530740 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
741 if err != nil || device == nil {
742 /*TODO: needs to handle error scenarios */
743 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
744 }
745 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000746 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400747
748 cloned := proto.Clone(device).(*voltha.Device)
749 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
750 cloned.OperStatus = voltha.OperStatus_UNKNOWN
751 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530752 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
753 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 -0400754 }
755
Chaitrashree G S44124192019-08-07 20:21:36 -0400756 // 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 +0530757 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400758 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530759 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400760 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400761 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
762 // all the modules initialized and ready to handle incoming ONUs.
763
Thomas Lee S985938d2020-05-04 11:40:41 +0530764 err = dh.initializeDeviceHandlerModules(ctx)
765 if err != nil {
766 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 -0400767 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400768
769 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800770 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530771 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400772 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800773 }
774 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700775
776 go startHeartbeatCheck(ctx, dh)
777
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400778 return nil
779 }
780
Neha Sharma8f4e4322020-08-06 10:51:53 +0000781 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400782 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400783 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400784 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400785 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400786 dh.populateActivePorts(ctx, ports)
787 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
788 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400789 }
790
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400791 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530792 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 -0400793 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530794
cuilin20187b2a8c32019-03-26 19:52:28 -0700795 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800796 go func() {
797 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400798 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800799 }
800 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000801 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000802
803 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000804 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000805 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700806
807 go startHeartbeatCheck(ctx, dh)
808
cuilin20187b2a8c32019-03-26 19:52:28 -0700809 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530810}
811
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400812func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000813 deviceInfo, err := dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400814
815 if err != nil {
816 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
817 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700818 dh.totalPonPorts = deviceInfo.GetPonPorts()
819
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400820 // Instantiate resource manager
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800821 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 -0400822 return olterrors.ErrResourceManagerInstantiating
823 }
824
Girish Gowdra9602eb42020-09-09 15:50:39 -0700825 dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400826
Girish Gowdra9602eb42020-09-09 15:50:39 -0700827 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
828 for i := range dh.flowMgr {
829 // Instantiate flow manager
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700830 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr, dh.groupMgr, uint32(i)); dh.flowMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700831 return olterrors.ErrResourceManagerInstantiating
832 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400833 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700834
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400835 /* TODO: Instantiate Alarm , stats , BW managers */
836 /* Instantiating Event Manager to handle Alarms and KPIs */
837 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
838
839 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000840 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400841
842 return nil
843
844}
845
Neha Sharma96b7bf22020-06-15 10:37:32 +0000846func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400847 var err error
848 var deviceInfo *oop.DeviceInfo
849
Neha Sharma8f4e4322020-08-06 10:51:53 +0000850 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400851
852 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000853 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400854 }
855 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000856 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400857 }
858
Neha Sharma96b7bf22020-06-15 10:37:32 +0000859 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400860 dh.device.Root = true
861 dh.device.Vendor = deviceInfo.Vendor
862 dh.device.Model = deviceInfo.Model
863 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
864 dh.device.HardwareVersion = deviceInfo.HardwareVersion
865 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
866
867 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000868 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400869 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000870 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400871 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000872 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400873 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000874 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400875 dh.device.MacAddress = genmac
876 } else {
877 dh.device.MacAddress = deviceInfo.DeviceId
878 }
879
880 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000881 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000882 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400883 }
884
885 return deviceInfo, nil
886}
887
Neha Sharma96b7bf22020-06-15 10:37:32 +0000888func startCollector(ctx context.Context, dh *DeviceHandler) {
889 logger.Debugf(ctx, "starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530890 for {
891 select {
892 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000893 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530894 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000895 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700896
Neha Sharma8f4e4322020-08-06 10:51:53 +0000897 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400898 if err != nil {
899 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
900 continue
901 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530902 for _, port := range ports {
903 // NNI Stats
904 if port.Type == voltha.Port_ETHERNET_NNI {
905 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
906 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000907 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000908 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000909 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530910 }
911 // PON Stats
912 if port.Type == voltha.Port_PON_OLT {
913 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
914 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
915 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000916 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000917 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530918 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000919 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000920
921 //ONU & Gem Stats
922 onuGemInfo := dh.flowMgr[intfID].onuGemInfo
923 if len(onuGemInfo) != 0 {
924 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfo)
925 }
Chaitrashree G Sef088112020-02-03 21:39:27 -0500926 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530927 }
928 }
929 }
930}
931
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700932//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530933func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400934 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000935 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530936 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530937
938 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400939 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
940 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530941 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530942}
943
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700944//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530945func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700946 return &ic.SwitchCapability{
947 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530948 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700949 HwDesc: "open_pon",
950 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700951 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -0700952 },
953 SwitchFeatures: &of.OfpSwitchFeatures{
954 NBuffers: 256,
955 NTables: 2,
956 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
957 of.OfpCapabilities_OFPC_TABLE_STATS |
958 of.OfpCapabilities_OFPC_PORT_STATS |
959 of.OfpCapabilities_OFPC_GROUP_STATS),
960 },
961 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530962}
963
Neha Sharma96b7bf22020-06-15 10:37:32 +0000964func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
965 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 -0700966 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700967 var deviceID string
968 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700969
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400970 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700971 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972 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 -0700973 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
974 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400975
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700976 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530977
978 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
979
Neha Sharma96b7bf22020-06-15 10:37:32 +0000980 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 -0700981 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700982 kwargs := make(map[string]interface{})
983 kwargs["onu_id"] = omciInd.OnuId
984 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700985
Neha Sharma8f4e4322020-08-06 10:51:53 +0000986 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700987 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530988 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700989 "intf-id": omciInd.IntfId,
990 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700991 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700992 deviceType = onuDevice.Type
993 deviceID = onuDevice.Id
994 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
995 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530996 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700997 } else {
998 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +0000999 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 +05301000 deviceType = onuInCache.(*OnuDevice).deviceType
1001 deviceID = onuInCache.(*OnuDevice).deviceID
1002 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -07001003 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001004
1005 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +00001006 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001007 ic.InterAdapterMessageType_OMCI_REQUEST, dh.openOLT.config.Topic, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001008 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301009 return olterrors.NewErrCommunication("omci-request", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001010 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001011 "destination": deviceType,
1012 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001013 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001014 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001015 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301016}
1017
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001018//ProcessInterAdapterMessage sends the proxied messages to the target device
1019// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1020// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001021func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
1022 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001023 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001024 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -07001025 fromTopic := msg.Header.FromTopic
1026 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001027 toDeviceID := msg.Header.ToDeviceId
1028 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -07001029
Neha Sharma96b7bf22020-06-15 10:37:32 +00001030 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 -07001031
1032 msgBody := msg.GetBody()
1033
1034 omciMsg := &ic.InterAdapterOmciMessage{}
1035 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001036 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001037 }
1038
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001039 if omciMsg.GetProxyAddress() == nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001040 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001041 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301042 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001044 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001045 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001046 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1047 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301048 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001049 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001050 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001051 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001052 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001053 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1054 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301055 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001056 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001057 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001058 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001059 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001060 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001061 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001062 }
1063 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301064}
1065
Neha Sharma96b7bf22020-06-15 10:37:32 +00001066func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001067 var intfID uint32
1068 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001069 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001070 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001071 intfID = onuDevice.ProxyAddress.GetChannelId()
1072 onuID = onuDevice.ProxyAddress.GetOnuId()
1073 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001074 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001075 intfID = omciMsg.GetProxyAddress().GetChannelId()
1076 onuID = omciMsg.GetProxyAddress().GetOnuId()
1077 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001078 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001079 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001080 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 -08001081
Thomas Lee S94109f12020-03-03 16:39:29 +05301082 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001083 "intf-id": intfID,
1084 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001085 }
1086
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001087 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1088 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001089 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001090 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1091 hex.Encode(hexPkt, omciMsg.Message)
1092 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1093
1094 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1095 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1096 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001097 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001098 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001099
Neha Sharma8f4e4322020-08-06 10:51:53 +00001100 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001101 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301102 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001103 "intf-id": intfID,
1104 "onu-id": onuID,
1105 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001106 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001108}
1109
David K. Bainbridge794735f2020-02-11 21:01:37 -08001110func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301111 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 -07001112 if err := dh.flowMgr[intfID].UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001113 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001114 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001115 // TODO: need resource manager
1116 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301117 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301118 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001119 st, _ := status.FromError(err)
1120 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001121 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1122
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001123 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301124 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001125 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001126 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001127 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001128 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001129 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001130}
1131
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133 channelID := onuDiscInd.GetIntfId()
1134 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001135
Neha Sharma96b7bf22020-06-15 10:37:32 +00001136 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301137
cuilin20187b2a8c32019-03-26 19:52:28 -07001138 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001139 if sn != "" {
1140 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001141 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001142 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001143 }
1144
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301145 var alarmInd oop.OnuAlarmIndication
1146 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001147 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301148
1149 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1150 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1151 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1152 OnuLosRaise event sent for it */
1153 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1154 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1155 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001156 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301157 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1158 "currentIntfId": onuDiscInd.GetIntfId()})
1159 // TODO:: Should we need to ignore raising OnuLosClear event
1160 // when onu connected to different PON?
1161 }
1162 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1163 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1164 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001165 go func() {
1166 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1167 logger.Debugw(ctx, "indication-failed", log.Fields{"error": err})
1168 }
1169 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301170 }
1171 return true
1172 })
1173
Neha Sharma96b7bf22020-06-15 10:37:32 +00001174 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001175 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001176 }
1177
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001178 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001179
1180 // check the ONU is already know to the OLT
1181 // NOTE the second time the ONU is discovered this should return a device
1182 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1183
1184 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001185 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 -08001186 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001187 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 -08001188 switch e.Code() {
1189 case codes.Internal:
1190 // this probably means NOT FOUND, so just create a new device
1191 onuDevice = nil
1192 case codes.DeadlineExceeded:
1193 // if the call times out, cleanup and exit
1194 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001195 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001196 }
1197 }
1198 }
1199
1200 if onuDevice == nil {
1201 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001202 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001203 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001204 ponintfid := onuDiscInd.GetIntfId()
npujarec5762e2020-01-01 14:08:48 +05301205 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001206
Neha Sharma96b7bf22020-06-15 10:37:32 +00001207 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001208
1209 if err != nil {
1210 // if we can't create an ID in resource manager,
1211 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001212 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001213 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001214 "pon-intf-id": ponintfid,
1215 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001216 }
1217
Neha Sharma8f4e4322020-08-06 10:51:53 +00001218 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001219 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001220 dh.discOnus.Delete(sn)
1221 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 +05301222 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001223 "pon-intf-id": ponintfid,
1224 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001225 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04001226 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano()); err != nil {
1227 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"error": err})
1228 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001229 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301230 log.Fields{"onuDevice": onuDevice,
1231 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001232 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301233 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001234 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001235
1236 // we can now use the existing ONU Id
1237 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001238 //Insert the ONU into cache to use in OnuIndication.
1239 //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 +00001240 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001241 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301242 "intfId": onuDiscInd.GetIntfId(),
1243 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001244 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001245
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301246 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301247 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001248 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301249 log.Fields{"onu": onuDev,
1250 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001251
Kent Hagermane6ff1012020-07-14 15:07:53 -04001252 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301253 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001254 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001255 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001256 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001257 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001258 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301259 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001260 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001261 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262 }
1263 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001264}
1265
Mahir Gunyel2fb81472020-12-16 23:18:34 -08001266func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication, serialNumber string) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001267
1268 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001269 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001270 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001271 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001272 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001273 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301274 log.Fields{"onuId": onuInd.OnuId,
1275 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301276 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001277 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301278
David K. Bainbridge794735f2020-02-11 21:01:37 -08001279 errFields := log.Fields{"device-id": dh.device.Id}
1280
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301281 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1282
Mahir Gunyele77977b2019-06-27 05:36:22 -07001283 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1284 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001285 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001286 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001287 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001288 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1289 if serialNumber != "" {
1290 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001291 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001292 } else {
1293 kwargs["onu_id"] = onuInd.OnuId
1294 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001295 errFields["onu-id"] = onuInd.OnuId
1296 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001297 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001298 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001299 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001300
David K. Bainbridge794735f2020-02-11 21:01:37 -08001301 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001302 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001303 }
1304
David K. Bainbridge794735f2020-02-11 21:01:37 -08001305 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001306 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001307 "previousIntfId": onuDevice.ParentPortNo,
1308 "currentIntfId": ponPort})
1309 }
1310
1311 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001312 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301313 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1314 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301315 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001316 }
1317 if !foundInCache {
1318 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1319
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301320 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 -08001321
1322 }
kesavand7cf3a052020-08-28 12:49:18 +05301323 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
1324 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().UnixNano()); err != nil {
1325 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"error": err})
1326 }
1327 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001328 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001329 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001330 }
1331 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001332}
1333
Neha Sharma96b7bf22020-06-15 10:37:32 +00001334func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001335 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 -07001336 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1337 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1338 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1339 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001340 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001341 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1342 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001343 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001344 onuInd.OperState = "down"
1345 }
1346 }
1347
David K. Bainbridge794735f2020-02-11 21:01:37 -08001348 switch onuInd.OperState {
1349 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001350 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 -07001351 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301352 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001353 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301355 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001356 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001357 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001358 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001359 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001360 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001361 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001362 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 -04001363 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301364 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001365 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301367 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001368 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001369 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001370 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001371 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001372 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001373 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001374 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001376 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001377}
1378
cuilin20187b2a8c32019-03-26 19:52:28 -07001379func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1380 if serialNum != nil {
1381 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001382 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001383 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001384}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001385func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1386 decodedStr, err := hex.DecodeString(serialNum[4:])
1387 if err != nil {
1388 return nil, err
1389 }
1390 return &oop.SerialNumber{
1391 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001392 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001393 }, nil
1394}
cuilin20187b2a8c32019-03-26 19:52:28 -07001395
1396func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1397 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001398 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001399 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1400 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1401 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1402 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1403 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1404 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1405 return tmp
1406}
1407
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001408//UpdateFlowsBulk upates the bulk flow
1409func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301410 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001411}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001412
1413//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001414func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1415 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301416 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001417 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301418 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001419 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001420 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001421 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001422 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001423 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001424 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001425 "intf-id": parentPort,
1426 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001427 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001428 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 -08001429 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301430}
1431
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001432// SendPacketInToCore sends packet-in to core
1433// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1434// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001435func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001436 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001437 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001438 "port": logicalPort,
1439 "packet": hex.EncodeToString(packetPayload),
1440 "device-id": dh.device.Id,
1441 })
1442 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001443 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 +05301444 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001445 "source": "adapter",
1446 "destination": "core",
1447 "device-id": dh.device.Id,
1448 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001449 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001450 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001451 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001452 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001453 "packet": hex.EncodeToString(packetPayload),
1454 "device-id": dh.device.Id,
1455 })
1456 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001457 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001458}
1459
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001460// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001461func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001462 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001463
1464 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1465 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001466 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001467 }
1468
Kent Hagermane6ff1012020-07-14 15:07:53 -04001469 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001470 metrics := dh.metrics.GetSubscriberMetrics()
1471 for _, m := range pmConfigs.Metrics {
1472 metrics[m.Name].Enabled = m.Enabled
1473
1474 }
1475 }
1476}
1477
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001478//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301479func (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 +00001480 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 +01001481
Girish Gowdra491a9c62021-01-06 16:43:07 -08001482 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001483 var errorsList []error
1484
Girish Gowdru0c588b22019-04-23 23:24:56 -04001485 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001486 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001487 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001488
Neha Sharma96b7bf22020-06-15 10:37:32 +00001489 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301490 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001491 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301492 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001493 if flow_utils.HasGroup(flow) {
1494 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1495 } else {
1496 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1497 }
Girish Gowdracefae192020-03-19 18:14:10 -07001498 if err != nil {
1499 errorsList = append(errorsList, err)
1500 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001501 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301502
1503 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001504 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001505 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301506 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001507 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301508 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001509 if flow_utils.HasGroup(flow) {
1510 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1511 } else {
1512 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1513 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001514 if err != nil {
1515 errorsList = append(errorsList, err)
1516 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301517 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001518 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001519
Girish Gowdracefae192020-03-19 18:14:10 -07001520 // 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 +00001521 if groups != nil {
1522 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001523 // err = dh.groupMgr.AddGroup(ctx, group)
1524 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001525 if err != nil {
1526 errorsList = append(errorsList, err)
1527 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001528 }
1529 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001530 // err = dh.groupMgr.ModifyGroup(ctx, group)
1531 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001532 if err != nil {
1533 errorsList = append(errorsList, err)
1534 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001535 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001536 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001537 // err = dh.groupMgr.DeleteGroup(ctx, group)
1538 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001539 if err != nil {
1540 errorsList = append(errorsList, err)
1541 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001542 }
1543 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001544 if len(errorsList) > 0 {
1545 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1546 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001547 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001548 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301549}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001550
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001551//DisableDevice disables the given device
1552//It marks the following for the given device:
1553//Device-Handler Admin-State : down
1554//Device Port-State: UNKNOWN
1555//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001556func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001557 /* On device disable ,admin state update has to be done prior sending request to agent since
1558 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001559 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001560 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001561 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001562 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001563 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001564 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001565 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001566 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001567 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001568 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301569
1570 dh.discOnus = sync.Map{}
1571 dh.onus = sync.Map{}
1572
Thomas Lee S85f37312020-04-03 17:06:12 +05301573 //stopping the stats collector
1574 dh.stopCollector <- true
1575
Neha Sharma96b7bf22020-06-15 10:37:32 +00001576 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001577 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301578 //Update device Admin state
1579 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001580 // 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 +00001581 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 -04001582 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001583 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001584 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001585 return nil
1586}
1587
Neha Sharma96b7bf22020-06-15 10:37:32 +00001588func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001589 // Update onu state as unreachable in onu adapter
1590 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301591 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001592 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001593 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001594 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001595 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 -04001596 }
1597 if onuDevices != nil {
1598 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001599 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001600 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001601 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001602 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001603 "From Adapter": dh.openOLT.config.Topic, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001604 }
1605
1606 }
1607 }
1608
1609}
1610
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001611//ReenableDevice re-enables the olt device after disable
1612//It marks the following for the given device:
1613//Device-Handler Admin-State : up
1614//Device Port-State: ACTIVE
1615//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001616func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001617 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301618 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001619 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301620 }
1621 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001622 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001623
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001624 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001625
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001626 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1627 if err != nil {
divyadesai3af43e12020-08-18 07:10:54 +00001628 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001629 }
1630 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001631 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001632 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001633 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001634 device.OperStatus = voltha.OperStatus_ACTIVE
1635 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001636
Neha Sharma8f4e4322020-08-06 10:51:53 +00001637 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 +05301638 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001639 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001640 "connect-status": device.ConnectStatus,
1641 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001642 }
kesavand39e0aa32020-01-28 20:58:50 -05001643
Neha Sharma96b7bf22020-06-15 10:37:32 +00001644 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001645
1646 return nil
1647}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001648
npujarec5762e2020-01-01 14:08:48 +05301649func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001650 var uniID uint32
1651 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301652 for _, port := range onu.UniPorts {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001653 uniID = UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001654 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001655 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001656 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001657 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001658 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001659 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301660 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001661 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301662 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001663 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001664 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001665 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301666 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001667 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001668 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301670 }
npujarec5762e2020-01-01 14:08:48 +05301671 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1672 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301674 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001675 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001676 if err = dh.resourceMgr.DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001677 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 +00001678 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001679 if err = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID)); err != nil {
1680 logger.Debugw(ctx, "failed-to-remove-flow-for", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
1681 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001682 }
1683 return nil
1684}
1685
npujarec5762e2020-01-01 14:08:48 +05301686func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001687 nniUniID := -1
1688 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301689
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001690 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301691 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001692 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001693 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301694 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301695 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001696 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001697 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001698 logger.Debugw(ctx, "nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301699 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301700 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001701 _ = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, nniIntfID, -1, -1)
1702
Devmalya Paul495b94a2019-08-27 19:42:00 -04001703 }
npujarec5762e2020-01-01 14:08:48 +05301704 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001705 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301706 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001707
David K. Bainbridge794735f2020-02-11 21:01:37 -08001708 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001709}
1710
1711// 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 +05301712func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001713 logger.Debug(ctx, "function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001714 /* Clear the KV store data associated with the all the UNI ports
1715 This clears up flow data and also resource map data for various
1716 other pon resources like alloc_id and gemport_id
1717 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001718 go dh.cleanupDeviceResources(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001719 logger.Debug(ctx, "removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001720 // Stop the Stats collector
1721 dh.stopCollector <- true
1722 // stop the heartbeat check routine
1723 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301724 dh.lockDevice.RLock()
1725 // Stop the read indication only if it the routine is active
1726 if dh.isReadIndicationRoutineActive {
1727 dh.stopIndications <- true
1728 }
1729 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001730 //Reset the state
1731 if dh.Client != nil {
1732 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301733 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001734 }
1735 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07001736 // There is no need to update the core about operation status and connection status of the OLT.
1737 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1738 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1739 // because the device does not exist in DB.
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001740 return nil
1741}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001742func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001743
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001744 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301745 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001746 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301747 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301748 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301749 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001750 _ = olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001751 "device-id": dh.device.Id,
Kent Hagermane6ff1012020-07-14 15:07:53 -04001752 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301753 }
1754 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301755 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001756 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301757 if err = dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001758 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301759 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301760 // Clear flowids for gem cache.
1761 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301762 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301763 }
1764 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301765 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301766 }
npujarec5762e2020-01-01 14:08:48 +05301767 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301768 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301769 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301770 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001771 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001772 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001773 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001774 /* Clear the flows from KV store associated with NNI port.
1775 There are mostly trap rules from NNI port (like LLDP)
1776 */
npujarec5762e2020-01-01 14:08:48 +05301777 if err := dh.clearNNIData(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001778 logger.Errorw(ctx, "failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001779 }
A R Karthick1f85b802019-10-11 05:06:05 +00001780
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001781 /* Clear the resource pool for each PON port in the background */
Kent Hagermane6ff1012020-07-14 15:07:53 -04001782 go func() {
1783 if err := dh.resourceMgr.Delete(ctx); err != nil {
1784 logger.Debug(ctx, err)
1785 }
1786 }()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001787 }
A R Karthick1f85b802019-10-11 05:06:05 +00001788
Devmalya Paul495b94a2019-08-27 19:42:00 -04001789 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301790 dh.onus.Range(func(key interface{}, value interface{}) bool {
1791 dh.onus.Delete(key)
1792 return true
1793 })
1794
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001795 /*Delete discovered ONU map for the device*/
1796 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1797 dh.discOnus.Delete(key)
1798 return true
1799 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001800}
1801
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001802//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001803func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001804 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301805 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001806 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001807 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001808 return nil
1809}
1810
David K. Bainbridge794735f2020-02-11 21:01:37 -08001811func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001812 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001813 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001814 "packet-indication": *packetIn,
1815 "device-id": dh.device.Id,
1816 "packet": hex.EncodeToString(packetIn.Pkt),
1817 })
1818 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001819 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001820 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001821 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001822 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001823 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001824 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001825 "logical-port-num": logicalPortNum,
1826 "device-id": dh.device.Id,
1827 "packet": hex.EncodeToString(packetIn.Pkt),
1828 })
1829 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830
Neha Sharma8f4e4322020-08-06 10:51:53 +00001831 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 +05301832 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001833 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301834 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001835 "device-id": dh.device.Id,
1836 "packet": hex.EncodeToString(packetIn.Pkt),
1837 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001838 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001839
Matteo Scandolo92186242020-06-12 10:54:18 -07001840 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001841 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001842 "packet": hex.EncodeToString(packetIn.Pkt),
1843 "device-id": dh.device.Id,
1844 })
1845 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001846 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001847}
1848
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001849// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301850func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001851 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001852 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001853 "device-id": dh.device.Id,
1854 "egress-port-no": egressPortNo,
1855 "pkt-length": len(packet.Data),
1856 "packet": hex.EncodeToString(packet.Data),
1857 })
1858 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001859
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001860 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001861 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001862 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1863 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301864 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1865 // Do not packet-out lldp packets on uni port.
1866 // ONOS has no clue about uni/nni ports, it just packets out on all
1867 // available ports on the Logical Switch. It should not be interested
1868 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001869 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001870 "device-id": dh.device.Id,
1871 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301872 return nil
1873 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001874 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1875 if innerEthType == 0x8100 {
1876 // q-in-q 802.1ad or 802.1q double tagged packet.
1877 // slice out the outer tag.
1878 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001879 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001880 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001881 "packet-data": hex.EncodeToString(packet.Data),
1882 "device-id": dh.device.Id,
1883 })
1884 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001885 }
1886 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001887 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1888 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001889 uniID := UniIDFromPortNum(uint32(egressPortNo))
1890
Girish Gowdra9602eb42020-09-09 15:50:39 -07001891 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001892 if err != nil {
1893 // In this case the openolt agent will receive the gemPortID as 0.
1894 // The agent tries to retrieve the gemPortID in this case.
1895 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001896 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001897 "intf-id": intfID,
1898 "onu-id": onuID,
1899 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001900 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301901 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001902 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001903 }
1904
1905 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07001906 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001907 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001908 "egress-port-no": egressPortNo,
1909 "intf-id": intfID,
1910 "onu-id": onuID,
1911 "uni-id": uniID,
1912 "gem-port-id": gemPortID,
1913 "packet": hex.EncodeToString(packet.Data),
1914 "device-id": dh.device.Id,
1915 })
1916 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001917
npujarec5762e2020-01-01 14:08:48 +05301918 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301919 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001920 "source": "adapter",
1921 "destination": "onu",
1922 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001923 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001924 "oni-id": onuID,
1925 "uni-id": uniID,
1926 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001927 "packet": hex.EncodeToString(packet.Data),
1928 "device-id": dh.device.Id,
1929 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001930 }
1931 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001932 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001933 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001934 return olterrors.NewErrInvalidValue(log.Fields{
1935 "egress-nni-port": egressPortNo,
1936 "device-id": dh.device.Id,
1937 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001938 }
1939 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001940
Matteo Scandolo92186242020-06-12 10:54:18 -07001941 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001942 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001943 "uplink-pkt": uplinkPkt,
1944 "packet": hex.EncodeToString(packet.Data),
1945 "device-id": dh.device.Id,
1946 })
1947 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001948
npujarec5762e2020-01-01 14:08:48 +05301949 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001950 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1951 "packet": hex.EncodeToString(packet.Data),
1952 "device-id": dh.device.Id,
1953 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001954 }
1955 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001956 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301957 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001958 "egressPortType": egressPortType,
1959 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301960 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001961 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001962 }
1963 return nil
1964}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001965
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001966func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1967 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001968}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301969
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001970func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001971
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301972 // start the heartbeat check towards the OLT.
1973 var timerCheck *time.Timer
1974
1975 for {
1976 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1977 select {
1978 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00001979 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001980 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001981 logger.Warnw(ctx, "hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301982 if timerCheck == nil {
1983 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001984 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301985 }
1986 } else {
1987 if timerCheck != nil {
1988 if timerCheck.Stop() {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001989 logger.Debugw(ctx, "got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301990 }
1991 timerCheck = nil
1992 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001993 logger.Debugw(ctx, "hearbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05301994 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301995 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301996 }
1997 cancel()
1998 case <-dh.stopHeartbeatCheck:
Neha Sharma96b7bf22020-06-15 10:37:32 +00001999 logger.Debugw(ctx, "stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302000 return
2001 }
2002 }
2003}
2004
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002005func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
2006 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
2007 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002008 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2009 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2010 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2011 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2012 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002013 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002014 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2015 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002016 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302017
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002018 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
2019 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002020 _ = 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 -04002021 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002022 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002023 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002024 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002025
2026 //raise olt communication failure event
2027 raisedTs := time.Now().UnixNano()
2028 device.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2029 device.OperStatus = voltha.OperStatus_UNKNOWN
2030 go dh.eventMgr.oltCommunicationEvent(ctx, device, raisedTs)
2031
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002032 go dh.cleanupDeviceResources(ctx)
2033
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002034 dh.lockDevice.RLock()
2035 // Stop the read indication only if it the routine is active
2036 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2037 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2038 // on next execution of the readIndication routine.
2039 if dh.isReadIndicationRoutineActive {
2040 dh.stopIndications <- true
2041 }
2042 dh.lockDevice.RUnlock()
2043
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002044 dh.transitionMap.Handle(ctx, DeviceInit)
2045
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302046 }
2047}
kesavand39e0aa32020-01-28 20:58:50 -05002048
2049// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002050func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2051 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2052 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002053}
2054
2055// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002056func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2057 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2058 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002059}
2060
kdarapu1afeceb2020-02-12 01:38:09 -05002061//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 +00002062func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2063 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002064 if port.GetType() == voltha.Port_ETHERNET_NNI {
2065 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002066 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302067 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302068 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002069 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002070 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002071 }
2072 // fetch interfaceid from PortNo
2073 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2074 ponIntf := &oop.Interface{IntfId: ponID}
2075 var operStatus voltha.OperStatus_Types
2076 if enablePort {
2077 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302078 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002079
2080 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302081 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002082 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002083 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002084 }
2085 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002086 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002087 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002088 } else {
2089 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302090 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002091 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302092 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002093 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002094 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002095 }
2096 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002097 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002098 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002099 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302100 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 +05302101 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302102 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002103 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002104 }
2105 return nil
2106}
2107
kdarapu1afeceb2020-02-12 01:38:09 -05002108//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002109func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002110 // Disable the port and update the oper_port_status to core
2111 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002112 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002113 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002114 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302115 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302116 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002117 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002118 }
2119 }
2120 }
2121 return nil
2122}
2123
2124//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002125func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2126 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2127 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002128 if port.Type == voltha.Port_ETHERNET_NNI {
2129 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002130 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002131 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002132 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002133 }
2134 }
2135 if port.Type == voltha.Port_PON_OLT {
2136 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002137 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002138 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002139 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002140 }
2141 }
2142 }
2143}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002144
2145// ChildDeviceLost deletes ONU and clears pon resources related to it.
2146func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
divyadesai3af43e12020-08-18 07:10:54 +00002147 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002148 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2149 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002150 onuDevice, ok := dh.onus.Load(onuKey)
2151 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302152 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002153 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002154 "device-id": dh.device.Id,
2155 "onu-id": onuID,
2156 "intf-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002157 }
2158 var sn *oop.SerialNumber
2159 var err error
2160 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302161 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002162 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302163 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002164 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2165 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002166
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002167 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Neha Sharma8f4e4322020-08-06 10:51:53 +00002168 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302169 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302170 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002171 "onu-id": onuID}, err).Log()
2172 }
2173 //clear PON resources associated with ONU
2174 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002175 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002176 logger.Warnw(ctx, "failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002177 "device-id": dh.device.Id,
2178 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002179 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002180 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002181 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002182 "device-id": dh.device.Id,
2183 "intf-id": intfID,
2184 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002185 } else {
2186 for i, onu := range onuGemData {
2187 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002188 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002189 if err := dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002190 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302191 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002192 "onu-device": onu,
2193 "error": err})
2194 }
2195 // Clear flowids for gem cache.
2196 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002197 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002198 }
2199 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002200 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002201 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002202 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002203 "intf-id": intfID,
2204 "onu-device": onu,
2205 "onu-gem": onuGemData,
2206 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002207 //Not returning error on cleanup.
2208 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002209 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002210 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002211 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002212 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002213 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002214 }
2215 }
2216 dh.onus.Delete(onuKey)
2217 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002218 dh.removeOnuIndicationChannels(ctx, onuDevice.(*OnuDevice).serialNumber)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002219 return nil
2220}
Girish Gowdracefae192020-03-19 18:14:10 -07002221
2222func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002223 for _, field := range flow_utils.GetOfbFields(flow) {
2224 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002225 return field.GetPort()
2226 }
2227 }
2228 return InvalidPort
2229}
2230
2231func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002232 for _, action := range flow_utils.GetActions(flow) {
2233 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002234 if out := action.GetOutput(); out != nil {
2235 return out.GetPort()
2236 }
2237 }
2238 }
2239 return InvalidPort
2240}
2241
Girish Gowdracefae192020-03-19 18:14:10 -07002242func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2243 inPort := getInPortFromFlow(flow)
2244 outPort := getOutPortFromFlow(flow)
2245
2246 if inPort == InvalidPort || outPort == InvalidPort {
2247 return inPort, outPort
2248 }
2249
2250 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2251 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2252 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002253 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002254 return uniPort, outPort
2255 }
2256 }
2257 } else {
2258 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2259 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002260 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002261 return inPort, uniPort
2262 }
2263 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2264 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002265 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002266 return uniPort, outPort
2267 }
2268 }
2269 }
2270
2271 return InvalidPort, InvalidPort
2272}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002273
2274func extractOmciTransactionID(omciPkt []byte) uint16 {
2275 if len(omciPkt) > 3 {
2276 d := omciPkt[0:2]
2277 transid := binary.BigEndian.Uint16(d)
2278 return transid
2279 }
2280 return 0
2281}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002282
2283// StoreOnuDevice stores the onu parameters to the local cache.
2284func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2285 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2286 dh.onus.Store(onuKey, onuDevice)
2287}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002288
Neha Sharma8f4e4322020-08-06 10:51:53 +00002289func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002290 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002291 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002292 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002293 resp := new(voltha.ReturnValues)
2294 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002295 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002296 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002297 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2298 return nil, err
2299 }
2300 ID = device.ProxyAddress.GetOnuId()
2301 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2302 valueparam.Onu = &Onu
2303 valueparam.Value = value
2304
2305 // This API is unsupported until agent patch is added
2306 resp.Unsupported = uint32(value)
2307 _ = ctx
2308
2309 // Uncomment this code once agent changes are complete and tests
2310 /*
2311 resp, err = dh.Client.GetValue(ctx, valueparam)
2312 if err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002313 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002314 return nil, err
2315 }
2316 */
2317
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002318 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 -08002319 return resp, nil
2320}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002321
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002322func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002323 // Default to PON0
2324 var intfID uint32
2325 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002326 if inPort != InvalidPort && outPort != InvalidPort {
2327 _, intfID, _, _ = ExtractAccessFromFlow(inPort, outPort)
2328 }
2329 return intfID
2330}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002331
2332func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, sn string) chan perOnuIndication {
2333 dh.perOnuChannelLock.Lock()
2334 if ch, ok := dh.perOnuChannel[sn]; ok {
2335 dh.perOnuChannelLock.Unlock()
2336 return ch.indicationChannel
2337 }
2338 channels := onuIndicationChannels{
2339 //We create a buffered channel here to avoid calling function to be blocked
2340 //in case of multiple indications from the same ONU,
2341 //especially in the case where indications are buffered in OLT.
2342 indicationChannel: make(chan perOnuIndication, 5),
2343 stopChannel: make(chan struct{}),
2344 }
2345 dh.perOnuChannel[sn] = channels
2346 dh.perOnuChannelLock.Unlock()
2347 go dh.perOnuIndicationsRoutine(&channels)
2348 return channels.indicationChannel
2349
2350}
2351
2352func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context, sn string) {
2353 logger.Debugw(ctx, "remove-onu-indication-channels", log.Fields{"sn": sn})
2354 dh.perOnuChannelLock.Lock()
2355 defer dh.perOnuChannelLock.Unlock()
2356 if ch, ok := dh.perOnuChannel[sn]; ok {
2357 close(ch.stopChannel)
2358 delete(dh.perOnuChannel, sn)
2359 }
2360
2361}
2362
2363func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, sn string) {
2364 ind := perOnuIndication{
2365 ctx: ctx,
2366 indication: indication,
2367 serialNumber: sn,
2368 }
2369 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "sn": sn})
2370 // Send the onuIndication on the ONU channel
2371 dh.getOnuIndicationChannel(ctx, sn) <- ind
2372}
2373
2374func (dh *DeviceHandler) perOnuIndicationsRoutine(onuChannels *onuIndicationChannels) {
2375 for {
2376 select {
2377 // process one indication per onu, before proceeding to the next one
2378 case onuInd := <-onuChannels.indicationChannel:
2379 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
2380 "ind": onuInd.indication, "sn": onuInd.serialNumber})
2381 switch onuInd.indication.Data.(type) {
2382 case *oop.Indication_OnuInd:
2383 if err := dh.onuIndication(onuInd.ctx, onuInd.indication.GetOnuInd(), onuInd.serialNumber); err != nil {
2384 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2385 "type": "onu-indication",
2386 "device-id": dh.device.Id,
2387 "sn": onuInd.serialNumber}, err).Log()
2388 }
2389 case *oop.Indication_OnuDiscInd:
2390 if err := dh.onuDiscIndication(onuInd.ctx, onuInd.indication.GetOnuDiscInd(), onuInd.serialNumber); err != nil {
2391 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2392 "type": "onu-discovery",
2393 "device-id": dh.device.Id,
2394 "sn": onuInd.serialNumber}, err).Log()
2395 }
2396 }
2397 case <-onuChannels.stopChannel:
2398 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2399 close(onuChannels.indicationChannel)
2400 return
2401 }
2402 }
2403}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002404
2405// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2406// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
2407func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *voltha.OfpFlowStats, group *voltha.OfpGroupEntry, action string) error {
2408 // Step1 : Fill McastFlowOrGroupControlBlock
2409 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2410 // Step3 : Wait on response channel for response
2411 // Step4 : Return error value
2412 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2413 errChan := make(chan error)
2414 var groupID uint32
2415 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2416 ctx: ctx,
2417 flowOrGroupAction: action,
2418 flow: flow,
2419 group: group,
2420 errChan: &errChan,
2421 }
2422 if flow != nil {
2423 groupID = flow_utils.GetGroup(flow)
2424 } else if group != nil {
2425 groupID = group.Desc.GroupId
2426 } else {
2427 return errors.New("flow-and-group-both-nil")
2428 }
2429 // Derive the appropriate go routine to handle the request by a simple module operation.
2430 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2431 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2432 // Wait for handler to return error value
2433 err := <-errChan
2434 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"flow": flow, "group": group, "action": action, "err": err})
2435 return err
2436}
2437
2438// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
2439func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock) {
2440 for {
2441 // block on the channel to receive an incoming mcast flow/group
2442 // process the flow completely before proceeding to handle the next flow
2443 mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel
2444 if mcastFlowOrGroupCb.flow != nil {
2445 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2446 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2447 log.Fields{"device-id": dh.device.Id,
2448 "flowToAdd": mcastFlowOrGroupCb.flow})
2449 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2450 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2451 // Pass the return value over the return channel
2452 *mcastFlowOrGroupCb.errChan <- err
2453 } else { // flow remove
2454 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2455 log.Fields{"device-id": dh.device.Id,
2456 "flowToRemove": mcastFlowOrGroupCb.flow})
2457 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2458 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2459 // Pass the return value over the return channel
2460 *mcastFlowOrGroupCb.errChan <- err
2461 }
2462 } else { // mcast group
2463 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2464 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2465 log.Fields{"device-id": dh.device.Id,
2466 "groupToAdd": mcastFlowOrGroupCb.group})
2467 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2468 // Pass the return value over the return channel
2469 *mcastFlowOrGroupCb.errChan <- err
2470 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2471 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2472 log.Fields{"device-id": dh.device.Id,
2473 "groupToModify": mcastFlowOrGroupCb.group})
2474 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2475 // Pass the return value over the return channel
2476 *mcastFlowOrGroupCb.errChan <- err
2477 } else { // group remove
2478 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2479 log.Fields{"device-id": dh.device.Id,
2480 "groupToRemove": mcastFlowOrGroupCb.group})
2481 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2482 // Pass the return value over the return channel
2483 *mcastFlowOrGroupCb.errChan <- err
2484 }
2485 }
2486 }
2487}
kesavand62126212021-01-12 04:56:06 -05002488
2489func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2490
2491 singleValResp := extension.SingleGetValueResponse{
2492 Response: &extension.GetValueResponse{
2493 Response: &extension.GetValueResponse_PortCoutners{
2494 PortCoutners: &extension.GetOltPortCountersResponse{},
2495 },
2496 },
2497 }
2498
2499 errResp := func(status extension.GetValueResponse_Status,
2500 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2501 return &extension.SingleGetValueResponse{
2502 Response: &extension.GetValueResponse{
2503 Status: status,
2504 ErrReason: reason,
2505 },
2506 }
2507 }
2508
2509 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2510 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2511 //send error response
2512 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2513 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2514 }
2515 statIndChn := make(chan bool, 1)
2516 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2517 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2518 //request openOlt agent to send the the port statistics indication
2519
2520 go func() {
2521 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2522 if err != nil {
2523 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2524 }
2525 }()
2526 select {
2527 case <-statIndChn:
2528 //indication received for ports stats
2529 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2530 case <-time.After(oltPortInfoTimeout * time.Second):
2531 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2532 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2533 case <-ctx.Done():
2534 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2535 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2536 }
2537 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2538 //get nni stats
2539 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
2540 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2541 cmnni := dh.portStats.collectNNIMetrics(intfID)
2542 if cmnni == nil {
2543 //TODO define the error reason
2544 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2545 }
2546 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2547 return &singleValResp
2548
2549 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2550 // get pon stats
2551 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
2552 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2553 cmpon := dh.portStats.collectPONMetrics(intfID)
2554 if cmpon == nil {
2555 //TODO define the error reason
2556 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2557 }
2558 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2559 return &singleValResp
2560 }
2561 }
2562 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2563}