blob: 2e4ae42a314568961ce84790dd02bed190d2da83 [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"
cuilin20187b2a8c32019-03-26 19:52:28 -070024 "fmt"
25 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040026 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070027 "strconv"
28 "strings"
29 "sync"
30 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053031
Matteo Scandolo945e4012019-12-12 14:16:11 -080032 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070033 "github.com/gogo/protobuf/proto"
34 "github.com/golang/protobuf/ptypes"
Girish Kumar93e91742020-07-27 16:43:19 +000035 grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
36 grpc_opentracing "github.com/grpc-ecosystem/go-grpc-middleware/tracing/opentracing"
Esin Karamanccb714b2019-11-29 15:02:06 +000037 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
Kent Hagermanf1db18b2020-07-08 13:38:15 -040038 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
Esin Karamanccb714b2019-11-29 15:02:06 +000039 "github.com/opencord/voltha-lib-go/v3/pkg/log"
40 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Thomas Lee S94109f12020-03-03 16:39:29 +053041 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080042 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000043 "github.com/opencord/voltha-protos/v3/go/common"
44 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
45 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
46 oop "github.com/opencord/voltha-protos/v3/go/openolt"
47 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070048 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040049 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040050 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053051)
52
salmansiddiqui7ac62132019-08-22 03:58:50 +000053// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040054const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000055 MaxRetry = 10
56 MaxTimeOutInMs = 500
Girish Gowdracefae192020-03-19 18:14:10 -070057 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040058)
59
Girish Gowdracefae192020-03-19 18:14:10 -070060// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
61type pendingFlowRemoveDataKey struct {
62 intfID uint32
63 onuID uint32
64 uniID uint32
65}
66
67// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
68// This holds the number of pending flow removes and also a signal channel to
69// to indicate the receiver when all flow removes are handled
70type pendingFlowRemoveData struct {
71 pendingFlowRemoveCount uint32
72 allFlowsRemoved chan struct{}
73}
74
Phaneendra Manda4c62c802019-03-06 21:37:49 +053075//DeviceHandler will interact with the OLT device.
76type DeviceHandler struct {
cuilin20187b2a8c32019-03-26 19:52:28 -070077 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053078 coreProxy adapterif.CoreProxy
79 AdapterProxy adapterif.AdapterProxy
80 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070081 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070082 exitChannel chan int
83 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053084 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070085 transitionMap *TransitionMap
86 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053087 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040088 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053089 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053090
Girish Gowdra3ab6d212020-03-24 17:33:15 -070091 discOnus sync.Map
92 onus sync.Map
93 portStats *OpenOltStatisticsMgr
94 metrics *pmmetrics.PmMetrics
95 stopCollector chan bool
96 stopHeartbeatCheck chan bool
97 activePorts sync.Map
98 stopIndications chan bool
99 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700100
101 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
102 // subscriber basis for the number of pending flow removes. This data is used
103 // to process all the flow removes for a subscriber before handling flow adds.
104 // Interleaving flow delete and flow add processing has known to cause PON resource
105 // management contentions on a per subscriber bases, so we need ensure ordering.
106 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107}
108
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700112 deviceType string
113 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 onuID uint32
115 intfID uint32
116 proxyDeviceID string
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530117 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400118 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700119}
120
Naga Manjunath7615e552019-10-11 22:35:47 +0530121var pmNames = []string{
122 "rx_bytes",
123 "rx_packets",
124 "rx_mcast_packets",
125 "rx_bcast_packets",
126 "tx_bytes",
127 "tx_packets",
128 "tx_mcast_packets",
129 "tx_bcast_packets",
130}
131
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700132//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530133func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700135 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700136 device.deviceType = deviceTp
137 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700138 device.onuID = onuID
139 device.intfID = intfID
140 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530141 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700142 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530143}
144
145//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530146func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700147 var dh DeviceHandler
148 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400149 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400150 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700151 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700152 dh.device = cloned
153 dh.openOLT = adapter
154 dh.exitChannel = make(chan int, 1)
155 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530156 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530157 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530158 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 -0500159 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400160 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700161 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
162
cuilin20187b2a8c32019-03-26 19:52:28 -0700163 //TODO initialize the support classes.
164 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530165}
166
167// start save the device to the data model
168func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700169 dh.lockDevice.Lock()
170 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000171 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700172 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000173 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530174}
175
176// stop stops the device dh. Not much to do for now
177func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700178 dh.lockDevice.Lock()
179 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000180 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700181 dh.exitChannel <- 1
Neha Sharma96b7bf22020-06-15 10:37:32 +0000182 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530183}
184
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400185func macifyIP(ip net.IP) string {
186 if len(ip) > 0 {
187 oct1 := strconv.FormatInt(int64(ip[12]), 16)
188 oct2 := strconv.FormatInt(int64(ip[13]), 16)
189 oct3 := strconv.FormatInt(int64(ip[14]), 16)
190 oct4 := strconv.FormatInt(int64(ip[15]), 16)
191 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
192 }
193 return ""
194}
195
Neha Sharma96b7bf22020-06-15 10:37:32 +0000196func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400197 var genmac string
198 var addr net.IP
199 var ips []string
200 var err error
201
Neha Sharma96b7bf22020-06-15 10:37:32 +0000202 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400203
204 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000205 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400206
207 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000208 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400209 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000210 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400211 }
212 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000213 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530214 log.Fields{"host": ips[0],
215 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400216 return genmac, nil
217 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000218 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400219 }
220
221 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000222 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530223 log.Fields{"host": host,
224 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400225 return genmac, nil
226}
227
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530228func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700229 slist := strings.Split(mac, ":")
230 result := make([]uint32, len(slist))
231 var err error
232 var tmp int64
233 for index, val := range slist {
234 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
235 return []uint32{1, 2, 3, 4, 5, 6}
236 }
237 result[index] = uint32(tmp)
238 }
239 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530240}
241
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700242//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 -0800243func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530244
David K. Bainbridge794735f2020-02-11 21:01:37 -0800245 switch portType {
246 case voltha.Port_ETHERNET_NNI:
247 return fmt.Sprintf("nni-%d", portNum), nil
248 case voltha.Port_PON_OLT:
249 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700250 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800251
Girish Kumarf26e4882020-03-05 06:49:10 +0000252 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530253}
254
Neha Sharma96b7bf22020-06-15 10:37:32 +0000255func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000256 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700257 if state == "up" {
258 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500259 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500260 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700261 } else {
262 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500263 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700264 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700265 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400266 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800267 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000268 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400269 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500270
Neha Sharma8f4e4322020-08-06 10:51:53 +0000271 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 +0000272 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
Neha Sharma8f4e4322020-08-06 10:51:53 +0000273 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 -0400274 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
275 "device-id": dh.device.Id,
276 "port-type": portType,
277 "port-number": portNum,
278 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500279 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400280 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500281 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400282 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700283 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400284 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700285 PortNo: portNum,
286 Label: label,
287 Type: portType,
288 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700289 OfpPort: &of.OfpPort{
290 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
291 Config: 0,
292 State: uint32(of.OfpPortState_OFPPS_LIVE),
293 Curr: capacity,
294 Advertised: capacity,
295 Peer: capacity,
296 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
297 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
298 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700299 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000300 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700301 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000302 if err := dh.coreProxy.PortCreated(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000303 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800304 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000305 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400306 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000307 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530308 return nil
309}
310
Kent Hagermane6ff1012020-07-14 15:07:53 -0400311func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530312 dh.lockDevice.Lock()
313 defer dh.lockDevice.Unlock()
Neha Sharma8f4e4322020-08-06 10:51:53 +0000314 device, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530315 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400316 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
317 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530318 }
319 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530320}
321
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700322// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530323// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800324func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000325 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700326 defer func() {
327 dh.lockDevice.Lock()
328 dh.isReadIndicationRoutineActive = false
329 dh.lockDevice.Unlock()
330 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700331 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700332 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700333 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700334 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400335 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530336 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400337 if err != nil || device == nil {
338 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000339 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400340 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400341
David Bainbridgef5879ca2019-12-13 21:17:54 +0000342 // Create an exponential backoff around re-enabling indications. The
343 // maximum elapsed time for the back off is set to 0 so that we will
344 // continue to retry. The max interval defaults to 1m, but is set
345 // here for code clarity
346 indicationBackoff := backoff.NewExponentialBackOff()
347 indicationBackoff.MaxElapsedTime = 0
348 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700349
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700350 dh.lockDevice.Lock()
351 dh.isReadIndicationRoutineActive = true
352 dh.lockDevice.Unlock()
353
Girish Gowdra3f974912020-03-23 20:35:18 -0700354Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700355 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400356 select {
357 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000358 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700359 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400360 default:
361 indication, err := indications.Recv()
362 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000363 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530364 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530365 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400366 // Use an exponential back off to prevent getting into a tight loop
367 duration := indicationBackoff.NextBackOff()
368 if duration == backoff.Stop {
369 // If we reach a maximum then warn and reset the backoff
370 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000371 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530372 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530373 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400374 indicationBackoff.Reset()
375 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700376
377 // On failure process a backoff timer while watching for stopIndications
378 // events
379 backoff := time.NewTimer(indicationBackoff.NextBackOff())
380 select {
381 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000382 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700383 if !backoff.Stop() {
384 <-backoff.C
385 }
386 break Loop
387 case <-backoff.C:
388 // backoff expired continue
389 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700390 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
391 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400392 }
393 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000394 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530395 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000396 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530397 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530398 "device-id": dh.device.Id})
399 if device.AdminState == voltha.AdminState_DELETED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000400 logger.Debug(ctx, "device-deleted--stopping-the-read-indication-thread")
Girish Gowdra3f974912020-03-23 20:35:18 -0700401 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400402 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700403 // Close the stream, and re-initialize it
404 if err = indications.CloseSend(); err != nil {
405 // Ok to ignore here, because we landed here due to a problem on the stream
406 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000407 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530408 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530409 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700410 }
411 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
412 return err
413 }
414 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400415 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530416 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400417 // Reset backoff if we have a successful receive
418 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400419 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530420 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000421 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530422 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530423 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400424 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400425 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400426 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700427 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700428 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700429 // Close the send stream
430 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700431
Girish Gowdra3f974912020-03-23 20:35:18 -0700432 return nil
433}
434
435func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
436
437 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
438 if err != nil {
439 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
440 }
441 if indications == nil {
442 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
443 }
444
445 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400446}
447
448// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
449func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
450 switch indication.Data.(type) {
451 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
452 return true
453
454 default:
455 return false
456 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700457}
458
David K. Bainbridge794735f2020-02-11 21:01:37 -0800459func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000460 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000461 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530462 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700463 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530464 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700465 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000466 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000467 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530468 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000469 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800470 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000471 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800472 }
473 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700474}
475
David K. Bainbridge794735f2020-02-11 21:01:37 -0800476// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530477func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400478 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700479 switch indication.Data.(type) {
480 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000481 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
482 defer span.Finish()
483
David K. Bainbridge794735f2020-02-11 21:01:37 -0800484 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400485 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800486 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700487 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000488 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
489 defer span.Finish()
490
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700491 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800492 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000493 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400494 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800495 }
496 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000497 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700498 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000499 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
500 defer span.Finish()
501
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700502 intfOperInd := indication.GetIntfOperInd()
503 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800504 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000505 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400506 _ = 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 -0800507 }
508 }()
Kent Hagermane6ff1012020-07-14 15:07:53 -0400509 if err := dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId()); err != nil {
510 logger.Warn(ctx, err)
511 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700512 } else if intfOperInd.GetType() == "pon" {
513 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
514 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800515 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000516 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400517 _ = 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 -0800518 }
519 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000520 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700521 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000522 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530523 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530524 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000526 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
527 defer span.Finish()
528
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700529 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000530 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700531 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800532 go func() {
533 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400534 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800535 }
536 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700537 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000538 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
539 defer span.Finish()
540
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000542 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800543 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000544 if err := dh.onuIndication(ctx, onuInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400545 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800546 }
547 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700548 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000549 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
550 defer span.Finish()
551
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700552 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000553 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 -0800554 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000555 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400556 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800557 }
558 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700559 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000560 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
561 defer span.Finish()
562
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700563 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000564 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700565 "intf-type": pktInd.IntfId,
566 "intf-id": pktInd.IntfId,
567 "gem-port-id": pktInd.GemportId,
568 "port-no": pktInd.PortNo,
569 "device-id": dh.device.Id,
570 })
571
572 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000573 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700574 "intf-type": pktInd.IntfId,
575 "intf-id": pktInd.IntfId,
576 "gem-port-id": pktInd.GemportId,
577 "port-no": pktInd.PortNo,
578 "packet": hex.EncodeToString(pktInd.Pkt),
579 "device-id": dh.device.Id,
580 })
581 }
582
David K. Bainbridge794735f2020-02-11 21:01:37 -0800583 go func() {
584 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400585 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800586 }
587 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700588 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000589 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
590 defer span.Finish()
591
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700592 portStats := indication.GetPortStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000593 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700594 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000595 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
596 defer span.Finish()
597
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700598 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000599 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700600 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000601 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
602 defer span.Finish()
603
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700604 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000605 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
606 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700607 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530608}
609
610// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530611func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530612 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000613 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530614
Girish Gowdru0c588b22019-04-23 23:24:56 -0400615 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530616 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400617 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000618 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400619 }
620 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530621}
622
623// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530624func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700625 dh.lockDevice.Lock()
626 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000627 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400628
npujarec5762e2020-01-01 14:08:48 +0530629 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400630 if err != nil || device == nil {
631 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000632 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400633 }
634
635 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400636
637 //Update the device oper state and connection status
638 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400639 dh.device = cloned
640
David K. Bainbridge794735f2020-02-11 21:01:37 -0800641 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000642 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400643 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400644
645 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530646 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400647 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000648 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400649 }
650 for _, onuDevice := range onuDevices.Items {
651
652 // Update onu state as down in onu adapter
653 onuInd := oop.OnuIndication{}
654 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800655 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800657 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400658 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800659 "source": "openolt",
660 "onu-indicator": onuInd,
661 "device-type": onuDevice.Type,
662 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700663 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700664 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400665 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700666 /* Discovered ONUs entries need to be cleared , since after OLT
667 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530668 dh.discOnus = sync.Map{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000669 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700670 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530671}
672
673// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530674func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400675 var err error
Girish Kumar93e91742020-07-27 16:43:19 +0000676 // Use Intercepters to automatically inject and publish Open Tracing Spans by this GRPC client
677 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
678 grpc.WithInsecure(),
679 grpc.WithBlock(),
680 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000681 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000682 )),
683 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000684 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000685 )))
686
687 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530688 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530689 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000690 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400691 }
692 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530693}
694
695// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530696func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400697 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530698 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400699 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530700}
701
702// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530703func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530704 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000705 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400706
707 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530708 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
709 if err != nil || device == nil {
710 /*TODO: needs to handle error scenarios */
711 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
712 }
713 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000714 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400715
716 cloned := proto.Clone(device).(*voltha.Device)
717 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
718 cloned.OperStatus = voltha.OperStatus_UNKNOWN
719 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530720 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
721 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 -0400722 }
723
Chaitrashree G S44124192019-08-07 20:21:36 -0400724 // 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 +0530725 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400726 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530727 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400728 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400729 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
730 // all the modules initialized and ready to handle incoming ONUs.
731
Thomas Lee S985938d2020-05-04 11:40:41 +0530732 err = dh.initializeDeviceHandlerModules(ctx)
733 if err != nil {
734 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 -0400735 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400736
737 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800738 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530739 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400740 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800741 }
742 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400743 return nil
744 }
745
Neha Sharma8f4e4322020-08-06 10:51:53 +0000746 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400747 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400748 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400749 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400750 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400751 dh.populateActivePorts(ctx, ports)
752 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
753 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400754 }
755
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400756 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530757 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 -0400758 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530759
cuilin20187b2a8c32019-03-26 19:52:28 -0700760 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800761 go func() {
762 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400763 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800764 }
765 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000766 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000767
768 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000769 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000770 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700771 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530772}
773
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400774func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000775 deviceInfo, err := dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400776
777 if err != nil {
778 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
779 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400780 // Instantiate resource manager
Neha Sharma3f221ae2020-04-29 19:02:12 +0000781 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, deviceInfo); dh.resourceMgr == nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400782 return olterrors.ErrResourceManagerInstantiating
783 }
784
785 // Instantiate flow manager
786 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
787 return olterrors.ErrResourceManagerInstantiating
788
789 }
790 /* TODO: Instantiate Alarm , stats , BW managers */
791 /* Instantiating Event Manager to handle Alarms and KPIs */
792 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
793
794 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000795 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400796
797 return nil
798
799}
800
Neha Sharma96b7bf22020-06-15 10:37:32 +0000801func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400802 var err error
803 var deviceInfo *oop.DeviceInfo
804
Neha Sharma8f4e4322020-08-06 10:51:53 +0000805 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400806
807 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000808 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400809 }
810 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000811 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400812 }
813
Neha Sharma96b7bf22020-06-15 10:37:32 +0000814 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400815 dh.device.Root = true
816 dh.device.Vendor = deviceInfo.Vendor
817 dh.device.Model = deviceInfo.Model
818 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
819 dh.device.HardwareVersion = deviceInfo.HardwareVersion
820 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
821
822 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000823 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400824 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000825 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400826 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000827 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400828 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000829 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400830 dh.device.MacAddress = genmac
831 } else {
832 dh.device.MacAddress = deviceInfo.DeviceId
833 }
834
835 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000836 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000837 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400838 }
839
840 return deviceInfo, nil
841}
842
Neha Sharma96b7bf22020-06-15 10:37:32 +0000843func startCollector(ctx context.Context, dh *DeviceHandler) {
844 logger.Debugf(ctx, "starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530845 for {
846 select {
847 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000848 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530849 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000850 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700851
Neha Sharma8f4e4322020-08-06 10:51:53 +0000852 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400853 if err != nil {
854 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
855 continue
856 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530857 for _, port := range ports {
858 // NNI Stats
859 if port.Type == voltha.Port_ETHERNET_NNI {
860 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
861 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000862 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
863 go dh.portStats.publishMetrics(ctx, cmnni, port, dh.device.Id, dh.device.Type)
864 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530865 }
866 // PON Stats
867 if port.Type == voltha.Port_PON_OLT {
868 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
869 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
870 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000871 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
872 go dh.portStats.publishMetrics(ctx, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530873 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000874 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500875 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530876 }
877 }
878 }
879}
880
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700881//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530882func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400883 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000884 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530885 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530886
887 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400888 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
889 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530890 }
891
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400892 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530893}
894
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700895//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530896func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700897 return &ic.SwitchCapability{
898 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530899 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700900 HwDesc: "open_pon",
901 SwDesc: "open_pon",
902 SerialNum: dh.device.SerialNumber,
903 },
904 SwitchFeatures: &of.OfpSwitchFeatures{
905 NBuffers: 256,
906 NTables: 2,
907 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
908 of.OfpCapabilities_OFPC_TABLE_STATS |
909 of.OfpCapabilities_OFPC_PORT_STATS |
910 of.OfpCapabilities_OFPC_GROUP_STATS),
911 },
912 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530913}
914
Neha Sharma96b7bf22020-06-15 10:37:32 +0000915func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
916 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 -0700917 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700918 var deviceID string
919 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700920
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400921 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700922 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000923 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 -0700924 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
925 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400926
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700927 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530928
929 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
930
Neha Sharma96b7bf22020-06-15 10:37:32 +0000931 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 -0700932 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700933 kwargs := make(map[string]interface{})
934 kwargs["onu_id"] = omciInd.OnuId
935 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700936
Neha Sharma8f4e4322020-08-06 10:51:53 +0000937 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530939 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700940 "intf-id": omciInd.IntfId,
941 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700942 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700943 deviceType = onuDevice.Type
944 deviceID = onuDevice.Id
945 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
946 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530947 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700948 } else {
949 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +0000950 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 +0530951 deviceType = onuInCache.(*OnuDevice).deviceType
952 deviceID = onuInCache.(*OnuDevice).deviceID
953 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700954 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700955
956 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +0000957 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
Thomas Lee S985938d2020-05-04 11:40:41 +0530958 ic.InterAdapterMessageType_OMCI_REQUEST, dh.device.Type, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800959 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530960 return olterrors.NewErrCommunication("omci-request", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530961 "source": dh.device.Type,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 "destination": deviceType,
963 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000964 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700965 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800966 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530967}
968
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700969//ProcessInterAdapterMessage sends the proxied messages to the target device
970// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
971// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
973 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700974 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700975 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700976 fromTopic := msg.Header.FromTopic
977 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700978 toDeviceID := msg.Header.ToDeviceId
979 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700980
Neha Sharma96b7bf22020-06-15 10:37:32 +0000981 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 -0700982
983 msgBody := msg.GetBody()
984
985 omciMsg := &ic.InterAdapterOmciMessage{}
986 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000987 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700988 }
989
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700990 if omciMsg.GetProxyAddress() == nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +0000991 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700992 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530993 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800994 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000995 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700996 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000997 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
998 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530999 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001000 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001001 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001003 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001004 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1005 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301006 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001007 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001008 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001009 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001010 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001011 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001012 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001013 }
1014 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301015}
1016
Neha Sharma96b7bf22020-06-15 10:37:32 +00001017func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001018 var intfID uint32
1019 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001020 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001021 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001022 intfID = onuDevice.ProxyAddress.GetChannelId()
1023 onuID = onuDevice.ProxyAddress.GetOnuId()
1024 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001025 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001026 intfID = omciMsg.GetProxyAddress().GetChannelId()
1027 onuID = omciMsg.GetProxyAddress().GetOnuId()
1028 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001029 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001030 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001031 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 -08001032
Thomas Lee S94109f12020-03-03 16:39:29 +05301033 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001034 "intf-id": intfID,
1035 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001036 }
1037
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001038 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1039 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001040 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001041 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1042 hex.Encode(hexPkt, omciMsg.Message)
1043 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1044
1045 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1046 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1047 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001048 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001049 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001050
Neha Sharma8f4e4322020-08-06 10:51:53 +00001051 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001052 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301053 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001054 "intf-id": intfID,
1055 "onu-id": onuID,
1056 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001057 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001058 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001059}
1060
David K. Bainbridge794735f2020-02-11 21:01:37 -08001061func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001062 logger.Debugw(ctx, "activate-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001063 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001064 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001065 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001066 // TODO: need resource manager
1067 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001068 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301069 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001070 st, _ := status.FromError(err)
1071 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001072 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1073
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001074 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301075 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001076 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001077 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001078 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001079 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001080 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001081}
1082
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001084 channelID := onuDiscInd.GetIntfId()
1085 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001086
Neha Sharma96b7bf22020-06-15 10:37:32 +00001087 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301088
cuilin20187b2a8c32019-03-26 19:52:28 -07001089 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001090 if sn != "" {
1091 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001092 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001093 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001094 }
1095
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301096 var alarmInd oop.OnuAlarmIndication
1097 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001098 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301099
1100 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1101 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1102 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1103 OnuLosRaise event sent for it */
1104 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1105 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1106 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001107 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301108 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1109 "currentIntfId": onuDiscInd.GetIntfId()})
1110 // TODO:: Should we need to ignore raising OnuLosClear event
1111 // when onu connected to different PON?
1112 }
1113 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1114 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1115 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001116 go func() {
1117 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1118 logger.Debugw(ctx, "indication-failed", log.Fields{"error": err})
1119 }
1120 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301121 }
1122 return true
1123 })
1124
Neha Sharma96b7bf22020-06-15 10:37:32 +00001125 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001127 }
1128
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001129 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001130
1131 // check the ONU is already know to the OLT
1132 // NOTE the second time the ONU is discovered this should return a device
1133 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1134
1135 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001136 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 -08001137 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 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 -08001139 switch e.Code() {
1140 case codes.Internal:
1141 // this probably means NOT FOUND, so just create a new device
1142 onuDevice = nil
1143 case codes.DeadlineExceeded:
1144 // if the call times out, cleanup and exit
1145 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001146 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001147 }
1148 }
1149 }
1150
1151 if onuDevice == nil {
1152 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001153 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001154 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001155 ponintfid := onuDiscInd.GetIntfId()
1156 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301157 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001158 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001159
Neha Sharma96b7bf22020-06-15 10:37:32 +00001160 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001161
1162 if err != nil {
1163 // if we can't create an ID in resource manager,
1164 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001165 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001166 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001167 "pon-intf-id": ponintfid,
1168 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001169 }
1170
Neha Sharma8f4e4322020-08-06 10:51:53 +00001171 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001172 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001173 dh.discOnus.Delete(sn)
1174 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 +05301175 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001176 "pon-intf-id": ponintfid,
1177 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001178 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04001179 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano()); err != nil {
1180 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"error": err})
1181 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001182 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301183 log.Fields{"onuDevice": onuDevice,
1184 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001185 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301186 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001187 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001188
1189 // we can now use the existing ONU Id
1190 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001191 //Insert the ONU into cache to use in OnuIndication.
1192 //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 +00001193 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001194 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301195 "intfId": onuDiscInd.GetIntfId(),
1196 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001197 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001198
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301199 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301200 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001201 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301202 log.Fields{"onu": onuDev,
1203 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001204
Kent Hagermane6ff1012020-07-14 15:07:53 -04001205 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301206 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001207 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001208 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001209 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001210 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001211 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301212 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001213 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001214 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001215 }
1216 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001217}
1218
Neha Sharma96b7bf22020-06-15 10:37:32 +00001219func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001220 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1221
1222 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001223 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001224 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001225 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001226 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001227 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301228 log.Fields{"onuId": onuInd.OnuId,
1229 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301230 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001231 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301232
David K. Bainbridge794735f2020-02-11 21:01:37 -08001233 errFields := log.Fields{"device-id": dh.device.Id}
1234
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301235 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1236
Mahir Gunyele77977b2019-06-27 05:36:22 -07001237 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1238 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001239 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001240 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001241 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001242 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1243 if serialNumber != "" {
1244 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001245 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001246 } else {
1247 kwargs["onu_id"] = onuInd.OnuId
1248 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001249 errFields["onu-id"] = onuInd.OnuId
1250 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001251 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001252 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001253 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001254
David K. Bainbridge794735f2020-02-11 21:01:37 -08001255 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001256 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001257 }
1258
David K. Bainbridge794735f2020-02-11 21:01:37 -08001259 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001260 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001261 "previousIntfId": onuDevice.ParentPortNo,
1262 "currentIntfId": ponPort})
1263 }
1264
1265 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001266 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301267 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1268 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301269 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001270 }
1271 if !foundInCache {
1272 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1273
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301274 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 -08001275
1276 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001277 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001278 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001279 }
1280 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001281}
1282
Neha Sharma96b7bf22020-06-15 10:37:32 +00001283func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001284 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 -07001285 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1286 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1287 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1288 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001289 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001290 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1291 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001292 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001293 onuInd.OperState = "down"
1294 }
1295 }
1296
David K. Bainbridge794735f2020-02-11 21:01:37 -08001297 switch onuInd.OperState {
1298 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001299 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 -07001300 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301301 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001302 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1303 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301304 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001305 "onu-indicator": onuInd,
1306 "source": "openolt",
1307 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001308 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001309 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001311 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 -04001312 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301313 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001314 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1315 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301316 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001317 "onu-indicator": onuInd,
1318 "source": "openolt",
1319 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001320 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001321 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001323 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001324 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001325 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001326}
1327
cuilin20187b2a8c32019-03-26 19:52:28 -07001328func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1329 if serialNum != nil {
1330 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001331 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001332 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001333}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001334func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1335 decodedStr, err := hex.DecodeString(serialNum[4:])
1336 if err != nil {
1337 return nil, err
1338 }
1339 return &oop.SerialNumber{
1340 VendorId: []byte(serialNum[:4]),
1341 VendorSpecific: []byte(decodedStr),
1342 }, nil
1343}
cuilin20187b2a8c32019-03-26 19:52:28 -07001344
1345func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1346 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001347 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001348 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1349 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1350 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1351 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1352 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1353 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1354 return tmp
1355}
1356
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001357//UpdateFlowsBulk upates the bulk flow
1358func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301359 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001360}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361
1362//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001363func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1364 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301365 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001366 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301367 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001368 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001369 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001370 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001371 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001372 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001373 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001374 "intf-id": parentPort,
1375 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001376 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001377 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 -08001378 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301379}
1380
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001381// SendPacketInToCore sends packet-in to core
1382// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1383// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001384func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001385 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001386 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001387 "port": logicalPort,
1388 "packet": hex.EncodeToString(packetPayload),
1389 "device-id": dh.device.Id,
1390 })
1391 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001392 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 +05301393 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001394 "source": "adapter",
1395 "destination": "core",
1396 "device-id": dh.device.Id,
1397 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001398 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001399 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001400 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001401 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001402 "packet": hex.EncodeToString(packetPayload),
1403 "device-id": dh.device.Id,
1404 })
1405 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001406 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001407}
1408
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001409// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001410func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001411 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001412
1413 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1414 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001415 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001416 }
1417
Kent Hagermane6ff1012020-07-14 15:07:53 -04001418 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001419 metrics := dh.metrics.GetSubscriberMetrics()
1420 for _, m := range pmConfigs.Metrics {
1421 metrics[m.Name].Enabled = m.Enabled
1422
1423 }
1424 }
1425}
1426
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301428func (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 +00001429 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 +01001430
1431 var errorsList []error
1432
Girish Gowdru0c588b22019-04-23 23:24:56 -04001433 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001434 for _, flow := range flows.ToRemove.Items {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001435 dh.incrementActiveFlowRemoveCount(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001436
Neha Sharma96b7bf22020-06-15 10:37:32 +00001437 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301438 log.Fields{"device-id": device.Id,
1439 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001440 err := dh.flowMgr.RemoveFlow(ctx, flow)
1441 if err != nil {
1442 errorsList = append(errorsList, err)
1443 }
1444
Neha Sharma96b7bf22020-06-15 10:37:32 +00001445 dh.decrementActiveFlowRemoveCount(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001446 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301447
1448 for _, flow := range flows.ToAdd.Items {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001449 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301450 log.Fields{"device-id": device.Id,
1451 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001452 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
Neha Sharma96b7bf22020-06-15 10:37:32 +00001453 dh.waitForFlowRemoveToFinish(ctx, flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001454 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1455 if err != nil {
1456 errorsList = append(errorsList, err)
1457 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301458 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001459 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001460
Girish Gowdracefae192020-03-19 18:14:10 -07001461 // 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 +00001462 if groups != nil {
1463 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001464 err := dh.flowMgr.AddGroup(ctx, group)
1465 if err != nil {
1466 errorsList = append(errorsList, err)
1467 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001468 }
1469 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001470 err := dh.flowMgr.ModifyGroup(ctx, group)
1471 if err != nil {
1472 errorsList = append(errorsList, err)
1473 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001474 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001475 for _, group := range groups.ToRemove.Items {
1476 err := dh.flowMgr.DeleteGroup(ctx, group)
1477 if err != nil {
1478 errorsList = append(errorsList, err)
1479 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001480 }
1481 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001482 if len(errorsList) > 0 {
1483 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1484 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001485 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001486 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301487}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001488
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001489//DisableDevice disables the given device
1490//It marks the following for the given device:
1491//Device-Handler Admin-State : down
1492//Device Port-State: UNKNOWN
1493//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001494func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001495 /* On device disable ,admin state update has to be done prior sending request to agent since
1496 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001497 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001498 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001499 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001500 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001501 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001502 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001503 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001504 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001505 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001506 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301507
1508 dh.discOnus = sync.Map{}
1509 dh.onus = sync.Map{}
1510
Thomas Lee S85f37312020-04-03 17:06:12 +05301511 //stopping the stats collector
1512 dh.stopCollector <- true
1513
Neha Sharma96b7bf22020-06-15 10:37:32 +00001514 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001515 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301516 //Update device Admin state
1517 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001518 // 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 +00001519 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 -04001520 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001521 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001522 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001523 return nil
1524}
1525
Neha Sharma96b7bf22020-06-15 10:37:32 +00001526func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001527 // Update onu state as unreachable in onu adapter
1528 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301529 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001530 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001531 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001532 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001533 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 -04001534 }
1535 if onuDevices != nil {
1536 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001537 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001538 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1539 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001540 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301541 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001542 }
1543
1544 }
1545 }
1546
1547}
1548
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001549//ReenableDevice re-enables the olt device after disable
1550//It marks the following for the given device:
1551//Device-Handler Admin-State : up
1552//Device Port-State: ACTIVE
1553//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001554func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001555 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301556 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001557 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301558 }
1559 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001560 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001561
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001562 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001563
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001564 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1565 if err != nil {
divyadesai3af43e12020-08-18 07:10:54 +00001566 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001567 }
1568 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001569 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001570 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001571 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001572 device.OperStatus = voltha.OperStatus_ACTIVE
1573 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001574
Neha Sharma8f4e4322020-08-06 10:51:53 +00001575 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 +05301576 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001577 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001578 "connect-status": device.ConnectStatus,
1579 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001580 }
kesavand39e0aa32020-01-28 20:58:50 -05001581
Neha Sharma96b7bf22020-06-15 10:37:32 +00001582 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001583
1584 return nil
1585}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001586
npujarec5762e2020-01-01 14:08:48 +05301587func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001588 var uniID uint32
1589 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301590 for _, port := range onu.UniPorts {
1591 uniID = UniIDFromPortNum(uint32(port))
Neha Sharma96b7bf22020-06-15 10:37:32 +00001592 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001593 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301594 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001595 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001596 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001597 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301598 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001599 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301600 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001601 }
npujarec5762e2020-01-01 14:08:48 +05301602 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001603 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301604 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001605 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001606 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001607 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301608 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001609 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001610 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001611 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301612 }
npujarec5762e2020-01-01 14:08:48 +05301613 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1614 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001615 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301616 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001617 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Esin Karaman7fb80c22020-07-16 14:23:33 +00001618 if err = dh.resourceMgr.DelGemPortPktInOfAllServices(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001619 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 +00001620 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001621 }
1622 return nil
1623}
1624
npujarec5762e2020-01-01 14:08:48 +05301625func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001626 nniUniID := -1
1627 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301628
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001629 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301630 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001631 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001632 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301633 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301634 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001635 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001636 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001637 logger.Debugw(ctx, "nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301638 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301639 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +00001640 logger.Debugw(ctx, "current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301641 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301642 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301643 }
npujarec5762e2020-01-01 14:08:48 +05301644 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001645 }
npujarec5762e2020-01-01 14:08:48 +05301646 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001647 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301648 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001649 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001650}
1651
1652// 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 +05301653func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001654 logger.Debug(ctx, "function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001655 /* Clear the KV store data associated with the all the UNI ports
1656 This clears up flow data and also resource map data for various
1657 other pon resources like alloc_id and gemport_id
1658 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001659 go dh.cleanupDeviceResources(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001660 logger.Debug(ctx, "removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001661 // Stop the Stats collector
1662 dh.stopCollector <- true
1663 // stop the heartbeat check routine
1664 dh.stopHeartbeatCheck <- true
1665 //Reset the state
1666 if dh.Client != nil {
1667 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301668 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001669 }
1670 }
1671 cloned := proto.Clone(device).(*voltha.Device)
1672 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1673 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1674 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1675 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1676 "device-id": device.Id,
1677 "connect-status": cloned.ConnectStatus,
1678 "oper-status": cloned.OperStatus}, err).Log()
1679 }
1680 return nil
1681}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001682func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001683
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001684 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301685 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1686 var ponPort uint32
1687 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1688 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301689 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301690 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001691 _ = olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001692 "device-id": dh.device.Id,
Kent Hagermane6ff1012020-07-14 15:07:53 -04001693 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301694 }
1695 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301696 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001697 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301698 if err = dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001699 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301700 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301701 // Clear flowids for gem cache.
1702 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301703 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301704 }
1705 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301706 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301707 }
npujarec5762e2020-01-01 14:08:48 +05301708 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301709 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301710 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301711 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001712 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001713 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001714 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001715 /* Clear the flows from KV store associated with NNI port.
1716 There are mostly trap rules from NNI port (like LLDP)
1717 */
npujarec5762e2020-01-01 14:08:48 +05301718 if err := dh.clearNNIData(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001719 logger.Errorw(ctx, "failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001720 }
A R Karthick1f85b802019-10-11 05:06:05 +00001721
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001722 /* Clear the resource pool for each PON port in the background */
Kent Hagermane6ff1012020-07-14 15:07:53 -04001723 go func() {
1724 if err := dh.resourceMgr.Delete(ctx); err != nil {
1725 logger.Debug(ctx, err)
1726 }
1727 }()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001728 }
A R Karthick1f85b802019-10-11 05:06:05 +00001729
Devmalya Paul495b94a2019-08-27 19:42:00 -04001730 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301731 dh.onus.Range(func(key interface{}, value interface{}) bool {
1732 dh.onus.Delete(key)
1733 return true
1734 })
1735
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001736 /*Delete discovered ONU map for the device*/
1737 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1738 dh.discOnus.Delete(key)
1739 return true
1740 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001741}
1742
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001743//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001744func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001745 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301746 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001747 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001748 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001749 return nil
1750}
1751
David K. Bainbridge794735f2020-02-11 21:01:37 -08001752func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001753 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001755 "packet-indication": *packetIn,
1756 "device-id": dh.device.Id,
1757 "packet": hex.EncodeToString(packetIn.Pkt),
1758 })
1759 }
npujarec5762e2020-01-01 14:08:48 +05301760 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001761 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001762 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001763 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001764 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001766 "logical-port-num": logicalPortNum,
1767 "device-id": dh.device.Id,
1768 "packet": hex.EncodeToString(packetIn.Pkt),
1769 })
1770 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001771
Neha Sharma8f4e4322020-08-06 10:51:53 +00001772 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 +05301773 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001774 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301775 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001776 "device-id": dh.device.Id,
1777 "packet": hex.EncodeToString(packetIn.Pkt),
1778 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001779 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001780
Matteo Scandolo92186242020-06-12 10:54:18 -07001781 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001782 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001783 "packet": hex.EncodeToString(packetIn.Pkt),
1784 "device-id": dh.device.Id,
1785 })
1786 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001787 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001788}
1789
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001790// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301791func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001792 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001793 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001794 "device-id": dh.device.Id,
1795 "egress-port-no": egressPortNo,
1796 "pkt-length": len(packet.Data),
1797 "packet": hex.EncodeToString(packet.Data),
1798 })
1799 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001801 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001802 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001803 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1804 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301805 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1806 // Do not packet-out lldp packets on uni port.
1807 // ONOS has no clue about uni/nni ports, it just packets out on all
1808 // available ports on the Logical Switch. It should not be interested
1809 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001810 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001811 "device-id": dh.device.Id,
1812 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301813 return nil
1814 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001815 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1816 if innerEthType == 0x8100 {
1817 // q-in-q 802.1ad or 802.1q double tagged packet.
1818 // slice out the outer tag.
1819 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001820 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001821 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001822 "packet-data": hex.EncodeToString(packet.Data),
1823 "device-id": dh.device.Id,
1824 })
1825 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001826 }
1827 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001828 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1829 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001830 uniID := UniIDFromPortNum(uint32(egressPortNo))
1831
Esin Karaman7fb80c22020-07-16 14:23:33 +00001832 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001833 if err != nil {
1834 // In this case the openolt agent will receive the gemPortID as 0.
1835 // The agent tries to retrieve the gemPortID in this case.
1836 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001837 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001838 "intf-id": intfID,
1839 "onu-id": onuID,
1840 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001841 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301842 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001843 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001844 }
1845
1846 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001847
Matteo Scandolo92186242020-06-12 10:54:18 -07001848 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001850 "egress-port-no": egressPortNo,
1851 "intf-id": intfID,
1852 "onu-id": onuID,
1853 "uni-id": uniID,
1854 "gem-port-id": gemPortID,
1855 "packet": hex.EncodeToString(packet.Data),
1856 "device-id": dh.device.Id,
1857 })
1858 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001859
npujarec5762e2020-01-01 14:08:48 +05301860 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301861 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001862 "source": "adapter",
1863 "destination": "onu",
1864 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001865 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001866 "oni-id": onuID,
1867 "uni-id": uniID,
1868 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001869 "packet": hex.EncodeToString(packet.Data),
1870 "device-id": dh.device.Id,
1871 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001872 }
1873 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001874 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001875 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001876 return olterrors.NewErrInvalidValue(log.Fields{
1877 "egress-nni-port": egressPortNo,
1878 "device-id": dh.device.Id,
1879 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001880 }
1881 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001882
Matteo Scandolo92186242020-06-12 10:54:18 -07001883 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001884 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001885 "uplink-pkt": uplinkPkt,
1886 "packet": hex.EncodeToString(packet.Data),
1887 "device-id": dh.device.Id,
1888 })
1889 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001890
npujarec5762e2020-01-01 14:08:48 +05301891 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001892 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1893 "packet": hex.EncodeToString(packet.Data),
1894 "device-id": dh.device.Id,
1895 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001896 }
1897 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001898 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301899 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001900 "egressPortType": egressPortType,
1901 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301902 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001903 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001904 }
1905 return nil
1906}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001907
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001908func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1909 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001910}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301911
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001912func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001913
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301914 // start the heartbeat check towards the OLT.
1915 var timerCheck *time.Timer
1916
1917 for {
1918 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1919 select {
1920 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00001921 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001922 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001923 logger.Warnw(ctx, "hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301924 if timerCheck == nil {
1925 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001926 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301927 }
1928 } else {
1929 if timerCheck != nil {
1930 if timerCheck.Stop() {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001931 logger.Debugw(ctx, "got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301932 }
1933 timerCheck = nil
1934 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001935 logger.Debugw(ctx, "hearbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05301936 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301937 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301938 }
1939 cancel()
1940 case <-dh.stopHeartbeatCheck:
Neha Sharma96b7bf22020-06-15 10:37:32 +00001941 logger.Debugw(ctx, "stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301942 return
1943 }
1944 }
1945}
1946
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001947func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1948 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1949 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001950 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001951 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301952
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001953 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1954 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001955 _ = 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 -04001956 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001957 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001958 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001959 }
1960 go dh.cleanupDeviceResources(ctx)
1961
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001962 dh.lockDevice.RLock()
1963 // Stop the read indication only if it the routine is active
1964 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1965 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1966 // on next execution of the readIndication routine.
1967 if dh.isReadIndicationRoutineActive {
1968 dh.stopIndications <- true
1969 }
1970 dh.lockDevice.RUnlock()
1971
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001972 dh.transitionMap.Handle(ctx, DeviceInit)
1973
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301974 }
1975}
kesavand39e0aa32020-01-28 20:58:50 -05001976
1977// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00001978func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
1979 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
1980 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001981}
1982
1983// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00001984func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
1985 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
1986 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001987}
1988
kdarapu1afeceb2020-02-12 01:38:09 -05001989//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 +00001990func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
1991 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05001992 if port.GetType() == voltha.Port_ETHERNET_NNI {
1993 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001994 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301995 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301996 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001997 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001998 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001999 }
2000 // fetch interfaceid from PortNo
2001 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2002 ponIntf := &oop.Interface{IntfId: ponID}
2003 var operStatus voltha.OperStatus_Types
2004 if enablePort {
2005 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302006 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002007
2008 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302009 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002010 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002011 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002012 }
2013 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002014 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002015 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002016 } else {
2017 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302018 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002019 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302020 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002021 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002022 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002023 }
2024 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002025 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002026 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002027 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302028 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 +05302029 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302030 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002031 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002032 }
2033 return nil
2034}
2035
kdarapu1afeceb2020-02-12 01:38:09 -05002036//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002037func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002038 // Disable the port and update the oper_port_status to core
2039 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002040 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002041 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002042 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302043 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302044 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002045 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002046 }
2047 }
2048 }
2049 return nil
2050}
2051
2052//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002053func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2054 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2055 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002056 if port.Type == voltha.Port_ETHERNET_NNI {
2057 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002058 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002059 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002060 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002061 }
2062 }
2063 if port.Type == voltha.Port_PON_OLT {
2064 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002065 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002066 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002067 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002068 }
2069 }
2070 }
2071}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002072
2073// ChildDeviceLost deletes ONU and clears pon resources related to it.
2074func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
divyadesai3af43e12020-08-18 07:10:54 +00002075 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002076 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2077 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002078 onuDevice, ok := dh.onus.Load(onuKey)
2079 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302080 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002081 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002082 "device-id": dh.device.Id,
2083 "onu-id": onuID,
2084 "intf-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002085 }
2086 var sn *oop.SerialNumber
2087 var err error
2088 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302089 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002090 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302091 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002092 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2093 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002094
2095 for uniID := 0; uniID < MaxUnisPerOnu; uniID++ {
2096 var flowRemoveData pendingFlowRemoveData
2097 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uint32(uniID)}
2098 dh.lockDevice.RLock()
2099 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2100 dh.lockDevice.RUnlock()
2101 continue
2102 }
2103 dh.lockDevice.RUnlock()
2104
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002105 logger.Debugw(ctx, "wait-for-flow-remove-complete-before-processing-child-device-lost",
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002106 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2107 // Wait for all flow removes to finish first
2108 <-flowRemoveData.allFlowsRemoved
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002109 logger.Debugw(ctx, "flow-removes-complete-for-subscriber",
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002110 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2111 }
2112
2113 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Neha Sharma8f4e4322020-08-06 10:51:53 +00002114 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302115 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302116 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002117 "onu-id": onuID}, err).Log()
2118 }
2119 //clear PON resources associated with ONU
2120 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002121 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002122 logger.Warnw(ctx, "failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002123 "device-id": dh.device.Id,
2124 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002125 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002126 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002127 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002128 "device-id": dh.device.Id,
2129 "intf-id": intfID,
2130 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002131 } else {
2132 for i, onu := range onuGemData {
2133 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002134 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002135 if err := dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002136 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302137 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002138 "onu-device": onu,
2139 "error": err})
2140 }
2141 // Clear flowids for gem cache.
2142 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002143 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002144 }
2145 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002146 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002147 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002148 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002149 "intf-id": intfID,
2150 "onu-device": onu,
2151 "onu-gem": onuGemData,
2152 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002153 //Not returning error on cleanup.
2154 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002155 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002156 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002157 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002158 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002159 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002160 }
2161 }
2162 dh.onus.Delete(onuKey)
2163 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2164 return nil
2165}
Girish Gowdracefae192020-03-19 18:14:10 -07002166
2167func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2168 for _, field := range flows.GetOfbFields(flow) {
2169 if field.Type == flows.IN_PORT {
2170 return field.GetPort()
2171 }
2172 }
2173 return InvalidPort
2174}
2175
2176func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2177 for _, action := range flows.GetActions(flow) {
2178 if action.Type == flows.OUTPUT {
2179 if out := action.GetOutput(); out != nil {
2180 return out.GetPort()
2181 }
2182 }
2183 }
2184 return InvalidPort
2185}
2186
Neha Sharma96b7bf22020-06-15 10:37:32 +00002187func (dh *DeviceHandler) incrementActiveFlowRemoveCount(ctx context.Context, flow *of.OfpFlowStats) {
Girish Gowdracefae192020-03-19 18:14:10 -07002188 inPort, outPort := getPorts(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002189 logger.Debugw(ctx, "increment-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002190 if inPort != InvalidPort && outPort != InvalidPort {
2191 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2192 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002193 logger.Debugw(ctx, "increment-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002194
2195 dh.lockDevice.Lock()
2196 defer dh.lockDevice.Unlock()
2197 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2198 if !ok {
2199 flowRemoveData = pendingFlowRemoveData{
2200 pendingFlowRemoveCount: 0,
2201 allFlowsRemoved: make(chan struct{}),
2202 }
2203 }
2204 flowRemoveData.pendingFlowRemoveCount++
2205 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2206
Neha Sharma96b7bf22020-06-15 10:37:32 +00002207 logger.Debugw(ctx, "current-flow-remove-count–increment",
Matteo Scandolo92186242020-06-12 10:54:18 -07002208 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
Girish Gowdracefae192020-03-19 18:14:10 -07002209 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2210 }
2211}
2212
Neha Sharma96b7bf22020-06-15 10:37:32 +00002213func (dh *DeviceHandler) decrementActiveFlowRemoveCount(ctx context.Context, flow *of.OfpFlowStats) {
Girish Gowdracefae192020-03-19 18:14:10 -07002214 inPort, outPort := getPorts(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002215 logger.Debugw(ctx, "decrement-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002216 if inPort != InvalidPort && outPort != InvalidPort {
2217 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2218 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002219 logger.Debugw(ctx, "decrement-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002220
2221 dh.lockDevice.Lock()
2222 defer dh.lockDevice.Unlock()
2223 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002224 logger.Fatalf(ctx, "flow-remove-key-not-found", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002225 } else {
2226 if val.pendingFlowRemoveCount > 0 {
2227 val.pendingFlowRemoveCount--
2228 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002229 logger.Debugw(ctx, "current-flow-remove-count-after-decrement",
Matteo Scandolo92186242020-06-12 10:54:18 -07002230 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
Girish Gowdracefae192020-03-19 18:14:10 -07002231 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2232 // If all flow removes have finished, then close the channel to signal the receiver
2233 // to go ahead with flow adds.
2234 if val.pendingFlowRemoveCount == 0 {
2235 close(val.allFlowsRemoved)
2236 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2237 return
2238 }
2239 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2240 }
2241 }
2242}
2243
Neha Sharma96b7bf22020-06-15 10:37:32 +00002244func (dh *DeviceHandler) waitForFlowRemoveToFinish(ctx context.Context, flow *of.OfpFlowStats) {
Girish Gowdracefae192020-03-19 18:14:10 -07002245 var flowRemoveData pendingFlowRemoveData
2246 var ok bool
2247 inPort, outPort := getPorts(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002248 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002249 if inPort != InvalidPort && outPort != InvalidPort {
2250 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2251 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002252 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002253
2254 dh.lockDevice.RLock()
2255 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002256 logger.Debugw(ctx, "no-pending-flow-to-remove", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002257 dh.lockDevice.RUnlock()
2258 return
2259 }
2260 dh.lockDevice.RUnlock()
2261
2262 // Wait for all flow removes to finish first
2263 <-flowRemoveData.allFlowsRemoved
2264
Neha Sharma96b7bf22020-06-15 10:37:32 +00002265 logger.Debugw(ctx, "all-flows-cleared--handling-flow-add-now", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002266 }
2267}
2268
2269func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2270 inPort := getInPortFromFlow(flow)
2271 outPort := getOutPortFromFlow(flow)
2272
2273 if inPort == InvalidPort || outPort == InvalidPort {
2274 return inPort, outPort
2275 }
2276
2277 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2278 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2279 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2280 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2281 return uniPort, outPort
2282 }
2283 }
2284 } else {
2285 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2286 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2287 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2288 return inPort, uniPort
2289 }
2290 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2291 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2292 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2293 return uniPort, outPort
2294 }
2295 }
2296 }
2297
2298 return InvalidPort, InvalidPort
2299}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002300
2301func extractOmciTransactionID(omciPkt []byte) uint16 {
2302 if len(omciPkt) > 3 {
2303 d := omciPkt[0:2]
2304 transid := binary.BigEndian.Uint16(d)
2305 return transid
2306 }
2307 return 0
2308}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002309
2310// StoreOnuDevice stores the onu parameters to the local cache.
2311func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2312 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2313 dh.onus.Store(onuKey, onuDevice)
2314}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002315
Neha Sharma8f4e4322020-08-06 10:51:53 +00002316func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002317 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002318 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002319 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002320 resp := new(voltha.ReturnValues)
2321 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002322 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002323 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002324 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2325 return nil, err
2326 }
2327 ID = device.ProxyAddress.GetOnuId()
2328 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2329 valueparam.Onu = &Onu
2330 valueparam.Value = value
2331
2332 // This API is unsupported until agent patch is added
2333 resp.Unsupported = uint32(value)
2334 _ = ctx
2335
2336 // Uncomment this code once agent changes are complete and tests
2337 /*
2338 resp, err = dh.Client.GetValue(ctx, valueparam)
2339 if err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002340 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002341 return nil, err
2342 }
2343 */
2344
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002345 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 -08002346 return resp, nil
2347}