blob: ef1b179559e88cb0d71b0db5beeead335c8bffae [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) {
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530342 dh.lockDevice.Lock()
343 defer dh.lockDevice.Unlock()
Neha Sharma8f4e4322020-08-06 10:51:53 +0000344 device, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530345 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400346 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
347 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530348 }
349 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 {
serkant.uluderya245caba2019-09-24 23:15:29 -0700653 dh.lockDevice.Lock()
654 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000655 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400656
npujarec5762e2020-01-01 14:08:48 +0530657 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400658 if err != nil || device == nil {
659 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000660 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400661 }
662
663 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400664
665 //Update the device oper state and connection status
666 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400667 dh.device = cloned
668
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 {
679
680 // Update onu state as down in onu adapter
681 onuInd := oop.OnuIndication{}
682 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800683 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +0300684 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800685 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400686 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +0300687 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800688 "onu-indicator": onuInd,
689 "device-type": onuDevice.Type,
690 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700691 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700692 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400693 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700694 /* Discovered ONUs entries need to be cleared , since after OLT
695 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530696 dh.discOnus = sync.Map{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000697 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700698 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530699}
700
701// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530702func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400703 var err error
Girish Kumar93e91742020-07-27 16:43:19 +0000704 // Use Intercepters to automatically inject and publish Open Tracing Spans by this GRPC client
705 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
706 grpc.WithInsecure(),
707 grpc.WithBlock(),
708 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000709 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000710 )),
711 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000712 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000713 )))
714
715 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530716 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530717 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000718 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400719 }
720 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530721}
722
723// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530724func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400725 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530726 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400727 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530728}
729
730// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530731func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530732 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000733 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400734
735 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530736 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
737 if err != nil || device == nil {
738 /*TODO: needs to handle error scenarios */
739 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
740 }
741 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000742 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400743
744 cloned := proto.Clone(device).(*voltha.Device)
745 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
746 cloned.OperStatus = voltha.OperStatus_UNKNOWN
747 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530748 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
749 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 -0400750 }
751
Chaitrashree G S44124192019-08-07 20:21:36 -0400752 // 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 +0530753 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400754 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530755 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400756 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400757 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
758 // all the modules initialized and ready to handle incoming ONUs.
759
Thomas Lee S985938d2020-05-04 11:40:41 +0530760 err = dh.initializeDeviceHandlerModules(ctx)
761 if err != nil {
762 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 -0400763 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400764
765 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800766 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530767 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400768 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800769 }
770 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700771
772 go startHeartbeatCheck(ctx, dh)
773
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400774 return nil
775 }
776
Neha Sharma8f4e4322020-08-06 10:51:53 +0000777 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400778 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400779 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400780 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400781 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400782 dh.populateActivePorts(ctx, ports)
783 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
784 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400785 }
786
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400787 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530788 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 -0400789 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530790
cuilin20187b2a8c32019-03-26 19:52:28 -0700791 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800792 go func() {
793 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400794 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800795 }
796 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000797 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000798
799 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000800 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000801 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700802
803 go startHeartbeatCheck(ctx, dh)
804
cuilin20187b2a8c32019-03-26 19:52:28 -0700805 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530806}
807
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400808func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000809 deviceInfo, err := dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400810
811 if err != nil {
812 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
813 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700814 dh.totalPonPorts = deviceInfo.GetPonPorts()
815
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400816 // Instantiate resource manager
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800817 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 -0400818 return olterrors.ErrResourceManagerInstantiating
819 }
820
Girish Gowdra9602eb42020-09-09 15:50:39 -0700821 dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400822
Girish Gowdra9602eb42020-09-09 15:50:39 -0700823 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
824 for i := range dh.flowMgr {
825 // Instantiate flow manager
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700826 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr, dh.groupMgr, uint32(i)); dh.flowMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700827 return olterrors.ErrResourceManagerInstantiating
828 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400829 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700830
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400831 /* TODO: Instantiate Alarm , stats , BW managers */
832 /* Instantiating Event Manager to handle Alarms and KPIs */
833 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
834
835 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000836 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400837
838 return nil
839
840}
841
Neha Sharma96b7bf22020-06-15 10:37:32 +0000842func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400843 var err error
844 var deviceInfo *oop.DeviceInfo
845
Neha Sharma8f4e4322020-08-06 10:51:53 +0000846 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400847
848 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000849 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400850 }
851 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000852 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400853 }
854
Neha Sharma96b7bf22020-06-15 10:37:32 +0000855 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400856 dh.device.Root = true
857 dh.device.Vendor = deviceInfo.Vendor
858 dh.device.Model = deviceInfo.Model
859 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
860 dh.device.HardwareVersion = deviceInfo.HardwareVersion
861 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
862
863 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000864 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400865 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000866 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400867 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000868 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400869 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000870 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400871 dh.device.MacAddress = genmac
872 } else {
873 dh.device.MacAddress = deviceInfo.DeviceId
874 }
875
876 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000877 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000878 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400879 }
880
881 return deviceInfo, nil
882}
883
Neha Sharma96b7bf22020-06-15 10:37:32 +0000884func startCollector(ctx context.Context, dh *DeviceHandler) {
885 logger.Debugf(ctx, "starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530886 for {
887 select {
888 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000889 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530890 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000891 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700892
Neha Sharma8f4e4322020-08-06 10:51:53 +0000893 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400894 if err != nil {
895 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
896 continue
897 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530898 for _, port := range ports {
899 // NNI Stats
900 if port.Type == voltha.Port_ETHERNET_NNI {
901 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
902 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000903 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000904 go dh.portStats.publishMetrics(ctx, NNIStats, cmnni, port, dh.device.Id, dh.device.Type)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000905 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530906 }
907 // PON Stats
908 if port.Type == voltha.Port_PON_OLT {
909 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
910 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
911 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000912 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000913 go dh.portStats.publishMetrics(ctx, PONStats, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530914 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000915 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000916
917 //ONU & Gem Stats
918 onuGemInfo := dh.flowMgr[intfID].onuGemInfo
919 if len(onuGemInfo) != 0 {
920 go dh.portStats.collectOnuAndGemStats(ctx, onuGemInfo)
921 }
Chaitrashree G Sef088112020-02-03 21:39:27 -0500922 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530923 }
924 }
925 }
926}
927
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700928//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530929func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400930 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000931 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530932 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530933
934 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400935 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
936 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530937 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530938}
939
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700940//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530941func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700942 return &ic.SwitchCapability{
943 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530944 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700945 HwDesc: "open_pon",
946 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700947 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -0700948 },
949 SwitchFeatures: &of.OfpSwitchFeatures{
950 NBuffers: 256,
951 NTables: 2,
952 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
953 of.OfpCapabilities_OFPC_TABLE_STATS |
954 of.OfpCapabilities_OFPC_PORT_STATS |
955 of.OfpCapabilities_OFPC_GROUP_STATS),
956 },
957 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530958}
959
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
961 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 -0700962 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700963 var deviceID string
964 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700965
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400966 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700967 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000968 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 -0700969 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
970 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400971
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700972 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530973
974 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
975
Neha Sharma96b7bf22020-06-15 10:37:32 +0000976 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 -0700977 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700978 kwargs := make(map[string]interface{})
979 kwargs["onu_id"] = omciInd.OnuId
980 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700981
Neha Sharma8f4e4322020-08-06 10:51:53 +0000982 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700983 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530984 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700985 "intf-id": omciInd.IntfId,
986 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700987 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 deviceType = onuDevice.Type
989 deviceID = onuDevice.Id
990 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
991 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530992 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700993 } else {
994 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +0000995 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 +0530996 deviceType = onuInCache.(*OnuDevice).deviceType
997 deviceID = onuInCache.(*OnuDevice).deviceID
998 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700999 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001000
1001 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +00001002 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001003 ic.InterAdapterMessageType_OMCI_REQUEST, dh.openOLT.config.Topic, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001004 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301005 return olterrors.NewErrCommunication("omci-request", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001006 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001007 "destination": deviceType,
1008 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001009 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001010 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001011 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301012}
1013
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014//ProcessInterAdapterMessage sends the proxied messages to the target device
1015// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
1016// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001017func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
1018 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001019 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001020 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -07001021 fromTopic := msg.Header.FromTopic
1022 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001023 toDeviceID := msg.Header.ToDeviceId
1024 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -07001025
Neha Sharma96b7bf22020-06-15 10:37:32 +00001026 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 -07001027
1028 msgBody := msg.GetBody()
1029
1030 omciMsg := &ic.InterAdapterOmciMessage{}
1031 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001032 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001033 }
1034
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001035 if omciMsg.GetProxyAddress() == nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001036 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001037 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301038 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001039 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001040 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001041 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001042 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1043 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301044 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001046 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001047 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001048 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001049 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1050 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301051 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001052 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001053 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001054 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001055 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001056 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001057 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001058 }
1059 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301060}
1061
Neha Sharma96b7bf22020-06-15 10:37:32 +00001062func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001063 var intfID uint32
1064 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001065 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001066 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001067 intfID = onuDevice.ProxyAddress.GetChannelId()
1068 onuID = onuDevice.ProxyAddress.GetOnuId()
1069 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001070 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001071 intfID = omciMsg.GetProxyAddress().GetChannelId()
1072 onuID = omciMsg.GetProxyAddress().GetOnuId()
1073 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001074 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001075 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 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 -08001077
Thomas Lee S94109f12020-03-03 16:39:29 +05301078 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001079 "intf-id": intfID,
1080 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001081 }
1082
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001083 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1084 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001085 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001086 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1087 hex.Encode(hexPkt, omciMsg.Message)
1088 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1089
1090 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1091 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1092 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001093 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001094 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001095
Neha Sharma8f4e4322020-08-06 10:51:53 +00001096 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001097 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301098 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001099 "intf-id": intfID,
1100 "onu-id": onuID,
1101 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001102 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001103 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001104}
1105
David K. Bainbridge794735f2020-02-11 21:01:37 -08001106func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301107 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 -07001108 if err := dh.flowMgr[intfID].UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001109 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001110 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001111 // TODO: need resource manager
1112 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301113 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301114 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001115 st, _ := status.FromError(err)
1116 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001117 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1118
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001119 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301120 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001121 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001122 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001123 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001124 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001126}
1127
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001129 channelID := onuDiscInd.GetIntfId()
1130 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001131
Neha Sharma96b7bf22020-06-15 10:37:32 +00001132 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301133
cuilin20187b2a8c32019-03-26 19:52:28 -07001134 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001135 if sn != "" {
1136 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001137 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001138 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001139 }
1140
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301141 var alarmInd oop.OnuAlarmIndication
1142 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001143 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301144
1145 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1146 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1147 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1148 OnuLosRaise event sent for it */
1149 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1150 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1151 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001152 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301153 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1154 "currentIntfId": onuDiscInd.GetIntfId()})
1155 // TODO:: Should we need to ignore raising OnuLosClear event
1156 // when onu connected to different PON?
1157 }
1158 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1159 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1160 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001161 go func() {
1162 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1163 logger.Debugw(ctx, "indication-failed", log.Fields{"error": err})
1164 }
1165 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301166 }
1167 return true
1168 })
1169
Neha Sharma96b7bf22020-06-15 10:37:32 +00001170 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001172 }
1173
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001174 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001175
1176 // check the ONU is already know to the OLT
1177 // NOTE the second time the ONU is discovered this should return a device
1178 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1179
1180 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001181 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 -08001182 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001183 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 -08001184 switch e.Code() {
1185 case codes.Internal:
1186 // this probably means NOT FOUND, so just create a new device
1187 onuDevice = nil
1188 case codes.DeadlineExceeded:
1189 // if the call times out, cleanup and exit
1190 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001191 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001192 }
1193 }
1194 }
1195
1196 if onuDevice == nil {
1197 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001198 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001199 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001200 ponintfid := onuDiscInd.GetIntfId()
npujarec5762e2020-01-01 14:08:48 +05301201 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001202
Neha Sharma96b7bf22020-06-15 10:37:32 +00001203 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001204
1205 if err != nil {
1206 // if we can't create an ID in resource manager,
1207 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001208 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001209 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001210 "pon-intf-id": ponintfid,
1211 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001212 }
1213
Neha Sharma8f4e4322020-08-06 10:51:53 +00001214 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001215 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001216 dh.discOnus.Delete(sn)
1217 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 +05301218 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001219 "pon-intf-id": ponintfid,
1220 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001221 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04001222 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano()); err != nil {
1223 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"error": err})
1224 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001225 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301226 log.Fields{"onuDevice": onuDevice,
1227 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001228 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301229 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001230 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001231
1232 // we can now use the existing ONU Id
1233 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001234 //Insert the ONU into cache to use in OnuIndication.
1235 //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 +00001236 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001237 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301238 "intfId": onuDiscInd.GetIntfId(),
1239 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001240 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001241
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301242 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301243 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001244 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301245 log.Fields{"onu": onuDev,
1246 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001247
Kent Hagermane6ff1012020-07-14 15:07:53 -04001248 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301249 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001251 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001252 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001253 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001254 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301255 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001257 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 }
1259 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001260}
1261
Mahir Gunyel2fb81472020-12-16 23:18:34 -08001262func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication, serialNumber string) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001263
1264 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001265 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001266 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001267 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001268 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001269 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301270 log.Fields{"onuId": onuInd.OnuId,
1271 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301272 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001273 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301274
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 errFields := log.Fields{"device-id": dh.device.Id}
1276
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301277 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1278
Mahir Gunyele77977b2019-06-27 05:36:22 -07001279 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1280 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001282 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001283 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001284 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1285 if serialNumber != "" {
1286 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001288 } else {
1289 kwargs["onu_id"] = onuInd.OnuId
1290 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001291 errFields["onu-id"] = onuInd.OnuId
1292 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001293 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001294 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001295 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001296
David K. Bainbridge794735f2020-02-11 21:01:37 -08001297 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001298 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001299 }
1300
David K. Bainbridge794735f2020-02-11 21:01:37 -08001301 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001302 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001303 "previousIntfId": onuDevice.ParentPortNo,
1304 "currentIntfId": ponPort})
1305 }
1306
1307 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001308 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301309 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1310 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301311 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001312 }
1313 if !foundInCache {
1314 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1315
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301316 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 -08001317
1318 }
kesavand7cf3a052020-08-28 12:49:18 +05301319 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
1320 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().UnixNano()); err != nil {
1321 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"error": err})
1322 }
1323 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001324 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001325 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 }
1327 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001328}
1329
Neha Sharma96b7bf22020-06-15 10:37:32 +00001330func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001331 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 -07001332 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1333 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1334 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1335 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001336 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001337 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1338 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001339 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001340 onuInd.OperState = "down"
1341 }
1342 }
1343
David K. Bainbridge794735f2020-02-11 21:01:37 -08001344 switch onuInd.OperState {
1345 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001346 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 -07001347 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301348 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001349 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001350 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301351 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001352 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001353 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001354 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001355 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001356 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001357 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001358 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 -04001359 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301360 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001361 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301363 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001364 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001365 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001366 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001367 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001368 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001370 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001371 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001372 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001373}
1374
cuilin20187b2a8c32019-03-26 19:52:28 -07001375func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1376 if serialNum != nil {
1377 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001378 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001379 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001380}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001381func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1382 decodedStr, err := hex.DecodeString(serialNum[4:])
1383 if err != nil {
1384 return nil, err
1385 }
1386 return &oop.SerialNumber{
1387 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001388 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001389 }, nil
1390}
cuilin20187b2a8c32019-03-26 19:52:28 -07001391
1392func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1393 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001394 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001395 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1396 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1397 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1398 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1399 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1400 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1401 return tmp
1402}
1403
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001404//UpdateFlowsBulk upates the bulk flow
1405func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301406 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001407}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001408
1409//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001410func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1411 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301412 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001413 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301414 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001415 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001416 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001417 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001418 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001419 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001420 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001421 "intf-id": parentPort,
1422 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001423 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001424 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 -08001425 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301426}
1427
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001428// SendPacketInToCore sends packet-in to core
1429// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1430// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001431func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001432 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001433 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001434 "port": logicalPort,
1435 "packet": hex.EncodeToString(packetPayload),
1436 "device-id": dh.device.Id,
1437 })
1438 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001439 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 +05301440 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001441 "source": "adapter",
1442 "destination": "core",
1443 "device-id": dh.device.Id,
1444 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001445 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001446 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001447 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001448 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001449 "packet": hex.EncodeToString(packetPayload),
1450 "device-id": dh.device.Id,
1451 })
1452 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001453 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001454}
1455
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001456// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001457func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001458 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001459
1460 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1461 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001462 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001463 }
1464
Kent Hagermane6ff1012020-07-14 15:07:53 -04001465 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001466 metrics := dh.metrics.GetSubscriberMetrics()
1467 for _, m := range pmConfigs.Metrics {
1468 metrics[m.Name].Enabled = m.Enabled
1469
1470 }
1471 }
1472}
1473
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001474//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301475func (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 +00001476 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 +01001477
Girish Gowdra491a9c62021-01-06 16:43:07 -08001478 var err error
Andrea Campanellac63bba92020-03-10 17:01:04 +01001479 var errorsList []error
1480
Girish Gowdru0c588b22019-04-23 23:24:56 -04001481 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001482 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001483 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001484
Neha Sharma96b7bf22020-06-15 10:37:32 +00001485 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301486 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001487 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301488 "flowToRemove": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001489 if flow_utils.HasGroup(flow) {
1490 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupRemove)
1491 } else {
1492 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
1493 }
Girish Gowdracefae192020-03-19 18:14:10 -07001494 if err != nil {
1495 errorsList = append(errorsList, err)
1496 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001497 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301498
1499 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001500 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001501 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301502 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001503 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301504 "flowToAdd": flow})
Girish Gowdra491a9c62021-01-06 16:43:07 -08001505 if flow_utils.HasGroup(flow) {
1506 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, flow, nil, McastFlowOrGroupAdd)
1507 } else {
1508 err = dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
1509 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001510 if err != nil {
1511 errorsList = append(errorsList, err)
1512 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301513 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001514 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001515
Girish Gowdracefae192020-03-19 18:14:10 -07001516 // 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 +00001517 if groups != nil {
1518 for _, group := range groups.ToAdd.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001519 // err = dh.groupMgr.AddGroup(ctx, group)
1520 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupAdd)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001521 if err != nil {
1522 errorsList = append(errorsList, err)
1523 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001524 }
1525 for _, group := range groups.ToUpdate.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001526 // err = dh.groupMgr.ModifyGroup(ctx, group)
1527 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupModify)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001528 if err != nil {
1529 errorsList = append(errorsList, err)
1530 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001531 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001532 for _, group := range groups.ToRemove.Items {
Girish Gowdra491a9c62021-01-06 16:43:07 -08001533 // err = dh.groupMgr.DeleteGroup(ctx, group)
1534 err = dh.RouteMcastFlowOrGroupMsgToChannel(ctx, nil, group, McastFlowOrGroupRemove)
Esin Karamand519bbf2020-07-01 11:16:03 +00001535 if err != nil {
1536 errorsList = append(errorsList, err)
1537 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001538 }
1539 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001540 if len(errorsList) > 0 {
1541 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1542 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001543 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001544 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301545}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001546
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001547//DisableDevice disables the given device
1548//It marks the following for the given device:
1549//Device-Handler Admin-State : down
1550//Device Port-State: UNKNOWN
1551//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001552func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001553 /* On device disable ,admin state update has to be done prior sending request to agent since
1554 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001555 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001556 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001557 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001558 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001559 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001560 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001561 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001562 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001563 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001564 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301565
1566 dh.discOnus = sync.Map{}
1567 dh.onus = sync.Map{}
1568
Thomas Lee S85f37312020-04-03 17:06:12 +05301569 //stopping the stats collector
1570 dh.stopCollector <- true
1571
Neha Sharma96b7bf22020-06-15 10:37:32 +00001572 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001573 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301574 //Update device Admin state
1575 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001576 // 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 +00001577 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 -04001578 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001579 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001580 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001581 return nil
1582}
1583
Neha Sharma96b7bf22020-06-15 10:37:32 +00001584func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001585 // Update onu state as unreachable in onu adapter
1586 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301587 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001588 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001589 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001590 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001591 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 -04001592 }
1593 if onuDevices != nil {
1594 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001595 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001596 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001597 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001599 "From Adapter": dh.openOLT.config.Topic, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001600 }
1601
1602 }
1603 }
1604
1605}
1606
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001607//ReenableDevice re-enables the olt device after disable
1608//It marks the following for the given device:
1609//Device-Handler Admin-State : up
1610//Device Port-State: ACTIVE
1611//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001612func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001613 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301614 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001615 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301616 }
1617 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001618 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001619
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001620 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001621
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001622 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1623 if err != nil {
divyadesai3af43e12020-08-18 07:10:54 +00001624 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001625 }
1626 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001627 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001628 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001629 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001630 device.OperStatus = voltha.OperStatus_ACTIVE
1631 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001632
Neha Sharma8f4e4322020-08-06 10:51:53 +00001633 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 +05301634 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001635 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001636 "connect-status": device.ConnectStatus,
1637 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001638 }
kesavand39e0aa32020-01-28 20:58:50 -05001639
Neha Sharma96b7bf22020-06-15 10:37:32 +00001640 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001641
1642 return nil
1643}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001644
npujarec5762e2020-01-01 14:08:48 +05301645func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001646 var uniID uint32
1647 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301648 for _, port := range onu.UniPorts {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001649 uniID = UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001650 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001651 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001652 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001653 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001654 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001655 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301656 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001657 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301658 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001659 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001660 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001661 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301662 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", 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-downstream", 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-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301666 }
npujarec5762e2020-01-01 14:08:48 +05301667 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1668 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001672 if err = dh.resourceMgr.DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 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 +00001674 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001675 if err = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID)); err != nil {
1676 logger.Debugw(ctx, "failed-to-remove-flow-for", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
1677 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001678 }
1679 return nil
1680}
1681
npujarec5762e2020-01-01 14:08:48 +05301682func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001683 nniUniID := -1
1684 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301685
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001686 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301687 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001688 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001689 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301690 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301691 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001692 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001693 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001694 logger.Debugw(ctx, "nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301695 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301696 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001697 _ = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, nniIntfID, -1, -1)
1698
Devmalya Paul495b94a2019-08-27 19:42:00 -04001699 }
npujarec5762e2020-01-01 14:08:48 +05301700 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001701 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301702 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001703
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001705}
1706
1707// 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 +05301708func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001709 logger.Debug(ctx, "function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001710 /* Clear the KV store data associated with the all the UNI ports
1711 This clears up flow data and also resource map data for various
1712 other pon resources like alloc_id and gemport_id
1713 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001714 go dh.cleanupDeviceResources(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001715 logger.Debug(ctx, "removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001716 // Stop the Stats collector
1717 dh.stopCollector <- true
1718 // stop the heartbeat check routine
1719 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301720 dh.lockDevice.RLock()
1721 // Stop the read indication only if it the routine is active
1722 if dh.isReadIndicationRoutineActive {
1723 dh.stopIndications <- true
1724 }
1725 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001726 //Reset the state
1727 if dh.Client != nil {
1728 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301729 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001730 }
1731 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07001732 // There is no need to update the core about operation status and connection status of the OLT.
1733 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1734 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1735 // because the device does not exist in DB.
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001736 return nil
1737}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001738func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001739
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001740 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301741 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001742 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301743 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301744 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301745 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001746 _ = olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001747 "device-id": dh.device.Id,
Kent Hagermane6ff1012020-07-14 15:07:53 -04001748 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301749 }
1750 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301751 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001752 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301753 if err = dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301755 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301756 // Clear flowids for gem cache.
1757 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301758 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301759 }
1760 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301761 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301762 }
npujarec5762e2020-01-01 14:08:48 +05301763 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301764 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301765 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301766 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001767 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001768 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001769 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001770 /* Clear the flows from KV store associated with NNI port.
1771 There are mostly trap rules from NNI port (like LLDP)
1772 */
npujarec5762e2020-01-01 14:08:48 +05301773 if err := dh.clearNNIData(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001774 logger.Errorw(ctx, "failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001775 }
A R Karthick1f85b802019-10-11 05:06:05 +00001776
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001777 /* Clear the resource pool for each PON port in the background */
Kent Hagermane6ff1012020-07-14 15:07:53 -04001778 go func() {
1779 if err := dh.resourceMgr.Delete(ctx); err != nil {
1780 logger.Debug(ctx, err)
1781 }
1782 }()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001783 }
A R Karthick1f85b802019-10-11 05:06:05 +00001784
Devmalya Paul495b94a2019-08-27 19:42:00 -04001785 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301786 dh.onus.Range(func(key interface{}, value interface{}) bool {
1787 dh.onus.Delete(key)
1788 return true
1789 })
1790
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001791 /*Delete discovered ONU map for the device*/
1792 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1793 dh.discOnus.Delete(key)
1794 return true
1795 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001796}
1797
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001798//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001799func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001800 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301801 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001802 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001803 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001804 return nil
1805}
1806
David K. Bainbridge794735f2020-02-11 21:01:37 -08001807func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001808 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001809 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001810 "packet-indication": *packetIn,
1811 "device-id": dh.device.Id,
1812 "packet": hex.EncodeToString(packetIn.Pkt),
1813 })
1814 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001815 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001816 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001817 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001818 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001819 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001820 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001821 "logical-port-num": logicalPortNum,
1822 "device-id": dh.device.Id,
1823 "packet": hex.EncodeToString(packetIn.Pkt),
1824 })
1825 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001826
Neha Sharma8f4e4322020-08-06 10:51:53 +00001827 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 +05301828 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001829 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301830 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001831 "device-id": dh.device.Id,
1832 "packet": hex.EncodeToString(packetIn.Pkt),
1833 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001834 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835
Matteo Scandolo92186242020-06-12 10:54:18 -07001836 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001837 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001838 "packet": hex.EncodeToString(packetIn.Pkt),
1839 "device-id": dh.device.Id,
1840 })
1841 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001842 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001843}
1844
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001845// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301846func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001847 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001848 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001849 "device-id": dh.device.Id,
1850 "egress-port-no": egressPortNo,
1851 "pkt-length": len(packet.Data),
1852 "packet": hex.EncodeToString(packet.Data),
1853 })
1854 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001855
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001856 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001857 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001858 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1859 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301860 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1861 // Do not packet-out lldp packets on uni port.
1862 // ONOS has no clue about uni/nni ports, it just packets out on all
1863 // available ports on the Logical Switch. It should not be interested
1864 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001865 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001866 "device-id": dh.device.Id,
1867 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301868 return nil
1869 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001870 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1871 if innerEthType == 0x8100 {
1872 // q-in-q 802.1ad or 802.1q double tagged packet.
1873 // slice out the outer tag.
1874 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001875 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001876 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001877 "packet-data": hex.EncodeToString(packet.Data),
1878 "device-id": dh.device.Id,
1879 })
1880 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001881 }
1882 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001883 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1884 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001885 uniID := UniIDFromPortNum(uint32(egressPortNo))
1886
Girish Gowdra9602eb42020-09-09 15:50:39 -07001887 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001888 if err != nil {
1889 // In this case the openolt agent will receive the gemPortID as 0.
1890 // The agent tries to retrieve the gemPortID in this case.
1891 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001892 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001893 "intf-id": intfID,
1894 "onu-id": onuID,
1895 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001896 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301897 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001898 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001899 }
1900
1901 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07001902 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001903 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001904 "egress-port-no": egressPortNo,
1905 "intf-id": intfID,
1906 "onu-id": onuID,
1907 "uni-id": uniID,
1908 "gem-port-id": gemPortID,
1909 "packet": hex.EncodeToString(packet.Data),
1910 "device-id": dh.device.Id,
1911 })
1912 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001913
npujarec5762e2020-01-01 14:08:48 +05301914 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301915 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001916 "source": "adapter",
1917 "destination": "onu",
1918 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001919 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001920 "oni-id": onuID,
1921 "uni-id": uniID,
1922 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001923 "packet": hex.EncodeToString(packet.Data),
1924 "device-id": dh.device.Id,
1925 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001926 }
1927 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001928 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001929 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001930 return olterrors.NewErrInvalidValue(log.Fields{
1931 "egress-nni-port": egressPortNo,
1932 "device-id": dh.device.Id,
1933 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001934 }
1935 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001936
Matteo Scandolo92186242020-06-12 10:54:18 -07001937 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001938 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001939 "uplink-pkt": uplinkPkt,
1940 "packet": hex.EncodeToString(packet.Data),
1941 "device-id": dh.device.Id,
1942 })
1943 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001944
npujarec5762e2020-01-01 14:08:48 +05301945 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001946 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1947 "packet": hex.EncodeToString(packet.Data),
1948 "device-id": dh.device.Id,
1949 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001950 }
1951 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001952 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301953 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001954 "egressPortType": egressPortType,
1955 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301956 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001957 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001958 }
1959 return nil
1960}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001961
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001962func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1963 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001964}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301965
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001966func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001967
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301968 // start the heartbeat check towards the OLT.
1969 var timerCheck *time.Timer
1970
1971 for {
1972 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1973 select {
1974 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00001975 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001976 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001977 logger.Warnw(ctx, "hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301978 if timerCheck == nil {
1979 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001980 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301981 }
1982 } else {
1983 if timerCheck != nil {
1984 if timerCheck.Stop() {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001985 logger.Debugw(ctx, "got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301986 }
1987 timerCheck = nil
1988 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001989 logger.Debugw(ctx, "hearbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05301990 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301991 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301992 }
1993 cancel()
1994 case <-dh.stopHeartbeatCheck:
Neha Sharma96b7bf22020-06-15 10:37:32 +00001995 logger.Debugw(ctx, "stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301996 return
1997 }
1998 }
1999}
2000
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002001func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
2002 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
2003 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07002004 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
2005 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
2006 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
2007 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
2008 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04002009 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07002010 // Immediately return, otherwise accessing a null 'device' struct would cause panic
2011 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002012 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302013
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002014 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
2015 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002016 _ = 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 -04002017 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002018 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002019 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002020 }
Gamze Abaka07868a52020-12-17 14:19:28 +00002021
2022 //raise olt communication failure event
2023 raisedTs := time.Now().UnixNano()
2024 device.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
2025 device.OperStatus = voltha.OperStatus_UNKNOWN
2026 go dh.eventMgr.oltCommunicationEvent(ctx, device, raisedTs)
2027
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002028 go dh.cleanupDeviceResources(ctx)
2029
Girish Gowdra3ab6d212020-03-24 17:33:15 -07002030 dh.lockDevice.RLock()
2031 // Stop the read indication only if it the routine is active
2032 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
2033 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
2034 // on next execution of the readIndication routine.
2035 if dh.isReadIndicationRoutineActive {
2036 dh.stopIndications <- true
2037 }
2038 dh.lockDevice.RUnlock()
2039
Chaitrashree G Sa4649252020-03-11 21:24:11 -04002040 dh.transitionMap.Handle(ctx, DeviceInit)
2041
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05302042 }
2043}
kesavand39e0aa32020-01-28 20:58:50 -05002044
2045// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002046func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
2047 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
2048 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05002049}
2050
2051// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002052func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2053 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2054 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002055}
2056
kdarapu1afeceb2020-02-12 01:38:09 -05002057//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 +00002058func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2059 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002060 if port.GetType() == voltha.Port_ETHERNET_NNI {
2061 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002062 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302063 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302064 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002065 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002066 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002067 }
2068 // fetch interfaceid from PortNo
2069 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2070 ponIntf := &oop.Interface{IntfId: ponID}
2071 var operStatus voltha.OperStatus_Types
2072 if enablePort {
2073 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302074 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002075
2076 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302077 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002078 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002079 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002080 }
2081 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002082 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002083 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002084 } else {
2085 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302086 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002087 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302088 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002089 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002090 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002091 }
2092 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002093 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002094 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002095 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302096 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 +05302097 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302098 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002099 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002100 }
2101 return nil
2102}
2103
kdarapu1afeceb2020-02-12 01:38:09 -05002104//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002105func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002106 // Disable the port and update the oper_port_status to core
2107 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002108 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002109 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002110 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302111 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302112 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002113 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002114 }
2115 }
2116 }
2117 return nil
2118}
2119
2120//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002121func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2122 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2123 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002124 if port.Type == voltha.Port_ETHERNET_NNI {
2125 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002126 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002127 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002128 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002129 }
2130 }
2131 if port.Type == voltha.Port_PON_OLT {
2132 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002133 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002134 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002135 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002136 }
2137 }
2138 }
2139}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002140
2141// ChildDeviceLost deletes ONU and clears pon resources related to it.
2142func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
divyadesai3af43e12020-08-18 07:10:54 +00002143 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002144 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2145 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002146 onuDevice, ok := dh.onus.Load(onuKey)
2147 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302148 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002149 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002150 "device-id": dh.device.Id,
2151 "onu-id": onuID,
2152 "intf-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002153 }
2154 var sn *oop.SerialNumber
2155 var err error
2156 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302157 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002158 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302159 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002160 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2161 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002162
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002163 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Neha Sharma8f4e4322020-08-06 10:51:53 +00002164 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302165 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302166 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002167 "onu-id": onuID}, err).Log()
2168 }
2169 //clear PON resources associated with ONU
2170 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002171 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002172 logger.Warnw(ctx, "failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002173 "device-id": dh.device.Id,
2174 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002175 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002176 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002177 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002178 "device-id": dh.device.Id,
2179 "intf-id": intfID,
2180 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002181 } else {
2182 for i, onu := range onuGemData {
2183 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002185 if err := dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002186 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302187 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002188 "onu-device": onu,
2189 "error": err})
2190 }
2191 // Clear flowids for gem cache.
2192 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002193 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002194 }
2195 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002196 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002197 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002198 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002199 "intf-id": intfID,
2200 "onu-device": onu,
2201 "onu-gem": onuGemData,
2202 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002203 //Not returning error on cleanup.
2204 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002205 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002206 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002207 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002208 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002209 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002210 }
2211 }
2212 dh.onus.Delete(onuKey)
2213 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002214 dh.removeOnuIndicationChannels(ctx, onuDevice.(*OnuDevice).serialNumber)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002215 return nil
2216}
Girish Gowdracefae192020-03-19 18:14:10 -07002217
2218func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002219 for _, field := range flow_utils.GetOfbFields(flow) {
2220 if field.Type == flow_utils.IN_PORT {
Girish Gowdracefae192020-03-19 18:14:10 -07002221 return field.GetPort()
2222 }
2223 }
2224 return InvalidPort
2225}
2226
2227func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002228 for _, action := range flow_utils.GetActions(flow) {
2229 if action.Type == flow_utils.OUTPUT {
Girish Gowdracefae192020-03-19 18:14:10 -07002230 if out := action.GetOutput(); out != nil {
2231 return out.GetPort()
2232 }
2233 }
2234 }
2235 return InvalidPort
2236}
2237
Girish Gowdracefae192020-03-19 18:14:10 -07002238func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2239 inPort := getInPortFromFlow(flow)
2240 outPort := getOutPortFromFlow(flow)
2241
2242 if inPort == InvalidPort || outPort == InvalidPort {
2243 return inPort, outPort
2244 }
2245
2246 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2247 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2248 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002249 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002250 return uniPort, outPort
2251 }
2252 }
2253 } else {
2254 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2255 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002256 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002257 return inPort, uniPort
2258 }
2259 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2260 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
Girish Gowdra491a9c62021-01-06 16:43:07 -08002261 if uniPort := flow_utils.GetChildPortFromTunnelId(flow); uniPort != 0 {
Girish Gowdracefae192020-03-19 18:14:10 -07002262 return uniPort, outPort
2263 }
2264 }
2265 }
2266
2267 return InvalidPort, InvalidPort
2268}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002269
2270func extractOmciTransactionID(omciPkt []byte) uint16 {
2271 if len(omciPkt) > 3 {
2272 d := omciPkt[0:2]
2273 transid := binary.BigEndian.Uint16(d)
2274 return transid
2275 }
2276 return 0
2277}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002278
2279// StoreOnuDevice stores the onu parameters to the local cache.
2280func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2281 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2282 dh.onus.Store(onuKey, onuDevice)
2283}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002284
Neha Sharma8f4e4322020-08-06 10:51:53 +00002285func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002286 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002287 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002288 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002289 resp := new(voltha.ReturnValues)
2290 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002291 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002292 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002293 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2294 return nil, err
2295 }
2296 ID = device.ProxyAddress.GetOnuId()
2297 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2298 valueparam.Onu = &Onu
2299 valueparam.Value = value
2300
2301 // This API is unsupported until agent patch is added
2302 resp.Unsupported = uint32(value)
2303 _ = ctx
2304
2305 // Uncomment this code once agent changes are complete and tests
2306 /*
2307 resp, err = dh.Client.GetValue(ctx, valueparam)
2308 if err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002309 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002310 return nil, err
2311 }
2312 */
2313
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002314 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 -08002315 return resp, nil
2316}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002317
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002318func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002319 // Default to PON0
2320 var intfID uint32
2321 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002322 if inPort != InvalidPort && outPort != InvalidPort {
2323 _, intfID, _, _ = ExtractAccessFromFlow(inPort, outPort)
2324 }
2325 return intfID
2326}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002327
2328func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, sn string) chan perOnuIndication {
2329 dh.perOnuChannelLock.Lock()
2330 if ch, ok := dh.perOnuChannel[sn]; ok {
2331 dh.perOnuChannelLock.Unlock()
2332 return ch.indicationChannel
2333 }
2334 channels := onuIndicationChannels{
2335 //We create a buffered channel here to avoid calling function to be blocked
2336 //in case of multiple indications from the same ONU,
2337 //especially in the case where indications are buffered in OLT.
2338 indicationChannel: make(chan perOnuIndication, 5),
2339 stopChannel: make(chan struct{}),
2340 }
2341 dh.perOnuChannel[sn] = channels
2342 dh.perOnuChannelLock.Unlock()
2343 go dh.perOnuIndicationsRoutine(&channels)
2344 return channels.indicationChannel
2345
2346}
2347
2348func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context, sn string) {
2349 logger.Debugw(ctx, "remove-onu-indication-channels", log.Fields{"sn": sn})
2350 dh.perOnuChannelLock.Lock()
2351 defer dh.perOnuChannelLock.Unlock()
2352 if ch, ok := dh.perOnuChannel[sn]; ok {
2353 close(ch.stopChannel)
2354 delete(dh.perOnuChannel, sn)
2355 }
2356
2357}
2358
2359func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, sn string) {
2360 ind := perOnuIndication{
2361 ctx: ctx,
2362 indication: indication,
2363 serialNumber: sn,
2364 }
2365 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "sn": sn})
2366 // Send the onuIndication on the ONU channel
2367 dh.getOnuIndicationChannel(ctx, sn) <- ind
2368}
2369
2370func (dh *DeviceHandler) perOnuIndicationsRoutine(onuChannels *onuIndicationChannels) {
2371 for {
2372 select {
2373 // process one indication per onu, before proceeding to the next one
2374 case onuInd := <-onuChannels.indicationChannel:
2375 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
2376 "ind": onuInd.indication, "sn": onuInd.serialNumber})
2377 switch onuInd.indication.Data.(type) {
2378 case *oop.Indication_OnuInd:
2379 if err := dh.onuIndication(onuInd.ctx, onuInd.indication.GetOnuInd(), onuInd.serialNumber); err != nil {
2380 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2381 "type": "onu-indication",
2382 "device-id": dh.device.Id,
2383 "sn": onuInd.serialNumber}, err).Log()
2384 }
2385 case *oop.Indication_OnuDiscInd:
2386 if err := dh.onuDiscIndication(onuInd.ctx, onuInd.indication.GetOnuDiscInd(), onuInd.serialNumber); err != nil {
2387 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2388 "type": "onu-discovery",
2389 "device-id": dh.device.Id,
2390 "sn": onuInd.serialNumber}, err).Log()
2391 }
2392 }
2393 case <-onuChannels.stopChannel:
2394 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2395 close(onuChannels.indicationChannel)
2396 return
2397 }
2398 }
2399}
Girish Gowdra491a9c62021-01-06 16:43:07 -08002400
2401// RouteMcastFlowOrGroupMsgToChannel routes incoming mcast flow or group to a channel to be handled by the a specific
2402// instance of mcastFlowOrGroupChannelHandlerRoutine meant to handle messages for that group.
2403func (dh *DeviceHandler) RouteMcastFlowOrGroupMsgToChannel(ctx context.Context, flow *voltha.OfpFlowStats, group *voltha.OfpGroupEntry, action string) error {
2404 // Step1 : Fill McastFlowOrGroupControlBlock
2405 // Step2 : Push the McastFlowOrGroupControlBlock to appropriate channel
2406 // Step3 : Wait on response channel for response
2407 // Step4 : Return error value
2408 logger.Debugw(ctx, "process-flow-or-group", log.Fields{"flow": flow, "group": group, "action": action})
2409 errChan := make(chan error)
2410 var groupID uint32
2411 mcastFlowOrGroupCb := McastFlowOrGroupControlBlock{
2412 ctx: ctx,
2413 flowOrGroupAction: action,
2414 flow: flow,
2415 group: group,
2416 errChan: &errChan,
2417 }
2418 if flow != nil {
2419 groupID = flow_utils.GetGroup(flow)
2420 } else if group != nil {
2421 groupID = group.Desc.GroupId
2422 } else {
2423 return errors.New("flow-and-group-both-nil")
2424 }
2425 // Derive the appropriate go routine to handle the request by a simple module operation.
2426 // There are only MaxNumOfGroupHandlerChannels number of channels to handle the mcast flow or group
2427 dh.incomingMcastFlowOrGroup[groupID%MaxNumOfGroupHandlerChannels] <- mcastFlowOrGroupCb
2428 // Wait for handler to return error value
2429 err := <-errChan
2430 logger.Debugw(ctx, "process-flow-or-group--received-resp", log.Fields{"flow": flow, "group": group, "action": action, "err": err})
2431 return err
2432}
2433
2434// mcastFlowOrGroupChannelHandlerRoutine routine to handle incoming mcast flow/group message
2435func (dh *DeviceHandler) mcastFlowOrGroupChannelHandlerRoutine(mcastFlowOrGroupChannel chan McastFlowOrGroupControlBlock) {
2436 for {
2437 // block on the channel to receive an incoming mcast flow/group
2438 // process the flow completely before proceeding to handle the next flow
2439 mcastFlowOrGroupCb := <-mcastFlowOrGroupChannel
2440 if mcastFlowOrGroupCb.flow != nil {
2441 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2442 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-flow",
2443 log.Fields{"device-id": dh.device.Id,
2444 "flowToAdd": mcastFlowOrGroupCb.flow})
2445 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2446 err := dh.flowMgr[0].AddFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow, nil)
2447 // Pass the return value over the return channel
2448 *mcastFlowOrGroupCb.errChan <- err
2449 } else { // flow remove
2450 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-flow",
2451 log.Fields{"device-id": dh.device.Id,
2452 "flowToRemove": mcastFlowOrGroupCb.flow})
2453 // The mcast flow is not unique to any particular PON port, so it is OK to default to PON0
2454 err := dh.flowMgr[0].RemoveFlow(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.flow)
2455 // Pass the return value over the return channel
2456 *mcastFlowOrGroupCb.errChan <- err
2457 }
2458 } else { // mcast group
2459 if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupAdd {
2460 logger.Debugw(mcastFlowOrGroupCb.ctx, "adding-mcast-group",
2461 log.Fields{"device-id": dh.device.Id,
2462 "groupToAdd": mcastFlowOrGroupCb.group})
2463 err := dh.groupMgr.AddGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2464 // Pass the return value over the return channel
2465 *mcastFlowOrGroupCb.errChan <- err
2466 } else if mcastFlowOrGroupCb.flowOrGroupAction == McastFlowOrGroupModify { // group modify
2467 logger.Debugw(mcastFlowOrGroupCb.ctx, "modifying-mcast-group",
2468 log.Fields{"device-id": dh.device.Id,
2469 "groupToModify": mcastFlowOrGroupCb.group})
2470 err := dh.groupMgr.ModifyGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2471 // Pass the return value over the return channel
2472 *mcastFlowOrGroupCb.errChan <- err
2473 } else { // group remove
2474 logger.Debugw(mcastFlowOrGroupCb.ctx, "removing-mcast-group",
2475 log.Fields{"device-id": dh.device.Id,
2476 "groupToRemove": mcastFlowOrGroupCb.group})
2477 err := dh.groupMgr.DeleteGroup(mcastFlowOrGroupCb.ctx, mcastFlowOrGroupCb.group)
2478 // Pass the return value over the return channel
2479 *mcastFlowOrGroupCb.errChan <- err
2480 }
2481 }
2482 }
2483}
kesavand62126212021-01-12 04:56:06 -05002484
2485func (dh *DeviceHandler) getOltPortCounters(ctx context.Context, oltPortInfo *extension.GetOltPortCounters) *extension.SingleGetValueResponse {
2486
2487 singleValResp := extension.SingleGetValueResponse{
2488 Response: &extension.GetValueResponse{
2489 Response: &extension.GetValueResponse_PortCoutners{
2490 PortCoutners: &extension.GetOltPortCountersResponse{},
2491 },
2492 },
2493 }
2494
2495 errResp := func(status extension.GetValueResponse_Status,
2496 reason extension.GetValueResponse_ErrorReason) *extension.SingleGetValueResponse {
2497 return &extension.SingleGetValueResponse{
2498 Response: &extension.GetValueResponse{
2499 Status: status,
2500 ErrReason: reason,
2501 },
2502 }
2503 }
2504
2505 if oltPortInfo.PortType != extension.GetOltPortCounters_Port_ETHERNET_NNI &&
2506 oltPortInfo.PortType != extension.GetOltPortCounters_Port_PON_OLT {
2507 //send error response
2508 logger.Debugw(ctx, "getOltPortCounters invalid portType", log.Fields{"oltPortInfo": oltPortInfo.PortType})
2509 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INVALID_PORT_TYPE)
2510 }
2511 statIndChn := make(chan bool, 1)
2512 dh.portStats.RegisterForStatIndication(ctx, portStatsType, statIndChn, oltPortInfo.PortNo, oltPortInfo.PortType)
2513 defer dh.portStats.DeRegisterFromStatIndication(ctx, portStatsType, statIndChn)
2514 //request openOlt agent to send the the port statistics indication
2515
2516 go func() {
2517 _, err := dh.Client.CollectStatistics(ctx, new(oop.Empty))
2518 if err != nil {
2519 logger.Errorw(ctx, "getOltPortCounters CollectStatistics failed ", log.Fields{"err": err})
2520 }
2521 }()
2522 select {
2523 case <-statIndChn:
2524 //indication received for ports stats
2525 logger.Debugw(ctx, "getOltPortCounters recvd statIndChn", log.Fields{"oltPortInfo": oltPortInfo})
2526 case <-time.After(oltPortInfoTimeout * time.Second):
2527 logger.Debugw(ctx, "getOltPortCounters timeout happened", log.Fields{"oltPortInfo": oltPortInfo})
2528 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2529 case <-ctx.Done():
2530 logger.Debugw(ctx, "getOltPortCounters ctx Done ", log.Fields{"oltPortInfo": oltPortInfo})
2531 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_TIMEOUT)
2532 }
2533 if oltPortInfo.PortType == extension.GetOltPortCounters_Port_ETHERNET_NNI {
2534 //get nni stats
2535 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_ETHERNET_NNI)
2536 logger.Debugw(ctx, "getOltPortCounters intfID ", log.Fields{"intfID": intfID})
2537 cmnni := dh.portStats.collectNNIMetrics(intfID)
2538 if cmnni == nil {
2539 //TODO define the error reason
2540 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2541 }
2542 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmnni)
2543 return &singleValResp
2544
2545 } else if oltPortInfo.PortType == extension.GetOltPortCounters_Port_PON_OLT {
2546 // get pon stats
2547 intfID := PortNoToIntfID(oltPortInfo.PortNo, voltha.Port_PON_OLT)
2548 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
2549 cmpon := dh.portStats.collectPONMetrics(intfID)
2550 if cmpon == nil {
2551 //TODO define the error reason
2552 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2553 }
2554 dh.portStats.updateGetOltPortCountersResponse(ctx, &singleValResp, cmpon)
2555 return &singleValResp
2556 }
2557 }
2558 return errResp(extension.GetValueResponse_ERROR, extension.GetValueResponse_INTERNAL_ERROR)
2559}