blob: 504526ff5ba26341fb25f1597c64556cfb5b38ed [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"
Girish Kumar93e91742020-07-27 16:43:19 +000048 "github.com/opentracing/opentracing-go"
cuilin20187b2a8c32019-03-26 19:52:28 -070049 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040050 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040051 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053052)
53
salmansiddiqui7ac62132019-08-22 03:58:50 +000054// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040055const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000056 MaxRetry = 10
57 MaxTimeOutInMs = 500
Girish Gowdracefae192020-03-19 18:14:10 -070058 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040059)
60
Girish Gowdracefae192020-03-19 18:14:10 -070061// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
62type pendingFlowRemoveDataKey struct {
63 intfID uint32
64 onuID uint32
65 uniID uint32
66}
67
68// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
69// This holds the number of pending flow removes and also a signal channel to
70// to indicate the receiver when all flow removes are handled
71type pendingFlowRemoveData struct {
72 pendingFlowRemoveCount uint32
73 allFlowsRemoved chan struct{}
74}
75
Phaneendra Manda4c62c802019-03-06 21:37:49 +053076//DeviceHandler will interact with the OLT device.
77type DeviceHandler struct {
cuilin20187b2a8c32019-03-26 19:52:28 -070078 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053079 coreProxy adapterif.CoreProxy
80 AdapterProxy adapterif.AdapterProxy
81 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070082 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070083 exitChannel chan int
84 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053085 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070086 transitionMap *TransitionMap
87 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053088 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040089 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053090 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053091
Girish Gowdra3ab6d212020-03-24 17:33:15 -070092 discOnus sync.Map
93 onus sync.Map
94 portStats *OpenOltStatisticsMgr
95 metrics *pmmetrics.PmMetrics
96 stopCollector chan bool
97 stopHeartbeatCheck chan bool
98 activePorts sync.Map
99 stopIndications chan bool
100 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700101
102 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
103 // subscriber basis for the number of pending flow removes. This data is used
104 // to process all the flow removes for a subscriber before handling flow adds.
105 // Interleaving flow delete and flow add processing has known to cause PON resource
106 // management contentions on a per subscriber bases, so we need ensure ordering.
107 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700108}
109
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700111type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700113 deviceType string
114 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115 onuID uint32
116 intfID uint32
117 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +0000118 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530119 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400120 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700121}
122
Naga Manjunath7615e552019-10-11 22:35:47 +0530123var pmNames = []string{
124 "rx_bytes",
125 "rx_packets",
126 "rx_mcast_packets",
127 "rx_bcast_packets",
128 "tx_bytes",
129 "tx_packets",
130 "tx_mcast_packets",
131 "tx_bcast_packets",
132}
133
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530135func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700136 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700137 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700138 device.deviceType = deviceTp
139 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 device.onuID = onuID
141 device.intfID = intfID
142 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000143 device.uniPorts = make(map[uint32]struct{})
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530144 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700145 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530146}
147
148//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530149func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700150 var dh DeviceHandler
151 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400152 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400153 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700154 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700155 dh.device = cloned
156 dh.openOLT = adapter
157 dh.exitChannel = make(chan int, 1)
158 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530159 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530160 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530161 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 -0500162 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400163 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700164 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
165
cuilin20187b2a8c32019-03-26 19:52:28 -0700166 //TODO initialize the support classes.
167 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530168}
169
170// start save the device to the data model
171func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700172 dh.lockDevice.Lock()
173 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000174 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700175 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000176 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530177}
178
179// stop stops the device dh. Not much to do for now
180func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700181 dh.lockDevice.Lock()
182 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000183 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700184 dh.exitChannel <- 1
Neha Sharma96b7bf22020-06-15 10:37:32 +0000185 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530186}
187
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400188func macifyIP(ip net.IP) string {
189 if len(ip) > 0 {
190 oct1 := strconv.FormatInt(int64(ip[12]), 16)
191 oct2 := strconv.FormatInt(int64(ip[13]), 16)
192 oct3 := strconv.FormatInt(int64(ip[14]), 16)
193 oct4 := strconv.FormatInt(int64(ip[15]), 16)
194 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
195 }
196 return ""
197}
198
Neha Sharma96b7bf22020-06-15 10:37:32 +0000199func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400200 var genmac string
201 var addr net.IP
202 var ips []string
203 var err error
204
Neha Sharma96b7bf22020-06-15 10:37:32 +0000205 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400206
207 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000208 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400209
210 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000211 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400212 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000213 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400214 }
215 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000216 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530217 log.Fields{"host": ips[0],
218 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400219 return genmac, nil
220 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000221 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400222 }
223
224 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000225 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530226 log.Fields{"host": host,
227 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400228 return genmac, nil
229}
230
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530231func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700232 slist := strings.Split(mac, ":")
233 result := make([]uint32, len(slist))
234 var err error
235 var tmp int64
236 for index, val := range slist {
237 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
238 return []uint32{1, 2, 3, 4, 5, 6}
239 }
240 result[index] = uint32(tmp)
241 }
242 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530243}
244
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700245//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 -0800246func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530247
David K. Bainbridge794735f2020-02-11 21:01:37 -0800248 switch portType {
249 case voltha.Port_ETHERNET_NNI:
250 return fmt.Sprintf("nni-%d", portNum), nil
251 case voltha.Port_PON_OLT:
252 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700253 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800254
Girish Kumarf26e4882020-03-05 06:49:10 +0000255 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530256}
257
Neha Sharma96b7bf22020-06-15 10:37:32 +0000258func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000259 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700260 if state == "up" {
261 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500262 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500263 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700264 } else {
265 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500266 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700267 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700268 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400269 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800270 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000271 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400272 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500273
Neha Sharma8f4e4322020-08-06 10:51:53 +0000274 if port, err := dh.coreProxy.GetDevicePort(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, portNum); err == nil && port.Type == portType {
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400275 log.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
Neha Sharma8f4e4322020-08-06 10:51:53 +0000276 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 -0400277 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
278 "device-id": dh.device.Id,
279 "port-type": portType,
280 "port-number": portNum,
281 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500282 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400283 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500284 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400285 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700286 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400287 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700288 PortNo: portNum,
289 Label: label,
290 Type: portType,
291 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700292 OfpPort: &of.OfpPort{
293 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
294 Config: 0,
295 State: uint32(of.OfpPortState_OFPPS_LIVE),
296 Curr: capacity,
297 Advertised: capacity,
298 Peer: capacity,
299 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
300 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
301 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700302 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000303 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700304 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000305 if err := dh.coreProxy.PortCreated(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000306 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800307 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000308 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400309 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000310 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530311 return nil
312}
313
Kent Hagermane6ff1012020-07-14 15:07:53 -0400314func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530315 dh.lockDevice.Lock()
316 defer dh.lockDevice.Unlock()
Neha Sharma8f4e4322020-08-06 10:51:53 +0000317 device, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530318 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400319 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
320 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530321 }
322 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530323}
324
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700325// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530326// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800327func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700329 defer func() {
330 dh.lockDevice.Lock()
331 dh.isReadIndicationRoutineActive = false
332 dh.lockDevice.Unlock()
333 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700334 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700335 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700336 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700337 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400338 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530339 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400340 if err != nil || device == nil {
341 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000342 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400343 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400344
David Bainbridgef5879ca2019-12-13 21:17:54 +0000345 // Create an exponential backoff around re-enabling indications. The
346 // maximum elapsed time for the back off is set to 0 so that we will
347 // continue to retry. The max interval defaults to 1m, but is set
348 // here for code clarity
349 indicationBackoff := backoff.NewExponentialBackOff()
350 indicationBackoff.MaxElapsedTime = 0
351 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700352
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700353 dh.lockDevice.Lock()
354 dh.isReadIndicationRoutineActive = true
355 dh.lockDevice.Unlock()
356
Girish Gowdra3f974912020-03-23 20:35:18 -0700357Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700358 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400359 select {
360 case <-dh.stopIndications:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000361 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700362 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400363 default:
364 indication, err := indications.Recv()
365 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000366 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530367 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530368 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400369 // Use an exponential back off to prevent getting into a tight loop
370 duration := indicationBackoff.NextBackOff()
371 if duration == backoff.Stop {
372 // If we reach a maximum then warn and reset the backoff
373 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000374 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530375 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530376 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400377 indicationBackoff.Reset()
378 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700379
380 // On failure process a backoff timer while watching for stopIndications
381 // events
382 backoff := time.NewTimer(indicationBackoff.NextBackOff())
383 select {
384 case <-dh.stopIndications:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000385 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700386 if !backoff.Stop() {
387 <-backoff.C
388 }
389 break Loop
390 case <-backoff.C:
391 // backoff expired continue
392 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700393 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
394 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400395 }
396 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000397 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530398 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000399 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530400 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530401 "device-id": dh.device.Id})
402 if device.AdminState == voltha.AdminState_DELETED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000403 logger.Debug(ctx, "device-deleted--stopping-the-read-indication-thread")
Girish Gowdra3f974912020-03-23 20:35:18 -0700404 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400405 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700406 // Close the stream, and re-initialize it
407 if err = indications.CloseSend(); err != nil {
408 // Ok to ignore here, because we landed here due to a problem on the stream
409 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000410 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530411 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530412 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700413 }
414 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
415 return err
416 }
417 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400418 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530419 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400420 // Reset backoff if we have a successful receive
421 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400422 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530423 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000424 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530425 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530426 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400427 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400428 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400429 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700430 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700431 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700432 // Close the send stream
433 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700434
Girish Gowdra3f974912020-03-23 20:35:18 -0700435 return nil
436}
437
438func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
439
440 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
441 if err != nil {
442 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
443 }
444 if indications == nil {
445 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
446 }
447
448 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400449}
450
451// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
452func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
453 switch indication.Data.(type) {
454 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
455 return true
456
457 default:
458 return false
459 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700460}
461
David K. Bainbridge794735f2020-02-11 21:01:37 -0800462func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000463 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000464 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530465 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700466 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530467 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700468 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000469 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000470 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530471 return olterrors.NewErrAdapter("failed-indication", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530472 "device_id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800473 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000474 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800475 }
476 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700477}
478
David K. Bainbridge794735f2020-02-11 21:01:37 -0800479// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530480func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400481 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700482 switch indication.Data.(type) {
483 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000484 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
485 defer span.Finish()
486
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400488 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800489 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000491 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
492 defer span.Finish()
493
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700494 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800495 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000496 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400497 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800498 }
499 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000500 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700501 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000502 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
503 defer span.Finish()
504
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700505 intfOperInd := indication.GetIntfOperInd()
506 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800507 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000508 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400509 _ = 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 -0800510 }
511 }()
Kent Hagermane6ff1012020-07-14 15:07:53 -0400512 if err := dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId()); err != nil {
513 logger.Warn(ctx, err)
514 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700515 } else if intfOperInd.GetType() == "pon" {
516 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
517 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800518 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000519 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400520 _ = 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 -0800521 }
522 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000523 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700524 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000525 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530526 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530527 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700528 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000529 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
530 defer span.Finish()
531
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700532 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000533 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700534 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800535 go func() {
536 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400537 _ = 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 -0800538 }
539 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700540 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000541 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
542 defer span.Finish()
543
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700544 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000545 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800546 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000547 if err := dh.onuIndication(ctx, onuInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400548 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800549 }
550 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700551 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000552 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
553 defer span.Finish()
554
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000556 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 -0800557 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000558 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400559 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800560 }
561 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700562 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000563 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
564 defer span.Finish()
565
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700566 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000567 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700568 "intf-type": pktInd.IntfId,
569 "intf-id": pktInd.IntfId,
570 "gem-port-id": pktInd.GemportId,
571 "port-no": pktInd.PortNo,
572 "device-id": dh.device.Id,
573 })
574
575 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000576 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700577 "intf-type": pktInd.IntfId,
578 "intf-id": pktInd.IntfId,
579 "gem-port-id": pktInd.GemportId,
580 "port-no": pktInd.PortNo,
581 "packet": hex.EncodeToString(pktInd.Pkt),
582 "device-id": dh.device.Id,
583 })
584 }
585
David K. Bainbridge794735f2020-02-11 21:01:37 -0800586 go func() {
587 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400588 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800589 }
590 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700591 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000592 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
593 defer span.Finish()
594
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700595 portStats := indication.GetPortStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000596 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700597 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000598 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
599 defer span.Finish()
600
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700601 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000602 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700603 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000604 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
605 defer span.Finish()
606
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700607 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000608 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
609 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700610 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530611}
612
613// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530614func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530615 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000616 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530617
Girish Gowdru0c588b22019-04-23 23:24:56 -0400618 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530619 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400620 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000621 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400622 }
623 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530624}
625
626// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530627func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700628 dh.lockDevice.Lock()
629 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000630 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400631
npujarec5762e2020-01-01 14:08:48 +0530632 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400633 if err != nil || device == nil {
634 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000635 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400636 }
637
638 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400639
640 //Update the device oper state and connection status
641 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400642 dh.device = cloned
643
David K. Bainbridge794735f2020-02-11 21:01:37 -0800644 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000645 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400646 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400647
648 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530649 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400650 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000651 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400652 }
653 for _, onuDevice := range onuDevices.Items {
654
655 // Update onu state as down in onu adapter
656 onuInd := oop.OnuIndication{}
657 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800658 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700659 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800660 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400661 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800662 "source": "openolt",
663 "onu-indicator": onuInd,
664 "device-type": onuDevice.Type,
665 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700666 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700667 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400668 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700669 /* Discovered ONUs entries need to be cleared , since after OLT
670 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530671 dh.discOnus = sync.Map{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000672 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700673 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530674}
675
676// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530677func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400678 var err error
Girish Kumar93e91742020-07-27 16:43:19 +0000679 // Use Intercepters to automatically inject and publish Open Tracing Spans by this GRPC client
680 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
681 grpc.WithInsecure(),
682 grpc.WithBlock(),
683 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
684 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer())),
685 )),
686 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
687 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer())),
688 )))
689
690 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530691 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530692 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000693 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400694 }
695 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530696}
697
698// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530699func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400700 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530701 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400702 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530703}
704
705// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530706func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530707 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000708 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400709
710 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530711 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
712 if err != nil || device == nil {
713 /*TODO: needs to handle error scenarios */
714 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
715 }
716 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000717 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400718
719 cloned := proto.Clone(device).(*voltha.Device)
720 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
721 cloned.OperStatus = voltha.OperStatus_UNKNOWN
722 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530723 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
724 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 -0400725 }
726
Chaitrashree G S44124192019-08-07 20:21:36 -0400727 // 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 +0530728 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400729 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530730 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400731 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400732 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
733 // all the modules initialized and ready to handle incoming ONUs.
734
Thomas Lee S985938d2020-05-04 11:40:41 +0530735 err = dh.initializeDeviceHandlerModules(ctx)
736 if err != nil {
737 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 -0400738 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400739
740 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800741 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530742 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400743 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800744 }
745 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400746 return nil
747 }
748
Neha Sharma8f4e4322020-08-06 10:51:53 +0000749 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400750 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400751 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400752 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400753 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400754 dh.populateActivePorts(ctx, ports)
755 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
756 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400757 }
758
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400759 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530760 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 -0400761 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530762
cuilin20187b2a8c32019-03-26 19:52:28 -0700763 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800764 go func() {
765 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400766 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800767 }
768 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000769 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000770
771 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000772 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000773 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700774 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530775}
776
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400777func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000778 deviceInfo, err := dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400779
780 if err != nil {
781 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
782 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400783 // Instantiate resource manager
Neha Sharma3f221ae2020-04-29 19:02:12 +0000784 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 -0400785 return olterrors.ErrResourceManagerInstantiating
786 }
787
788 // Instantiate flow manager
789 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
790 return olterrors.ErrResourceManagerInstantiating
791
792 }
793 /* TODO: Instantiate Alarm , stats , BW managers */
794 /* Instantiating Event Manager to handle Alarms and KPIs */
795 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
796
797 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000798 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400799
800 return nil
801
802}
803
Neha Sharma96b7bf22020-06-15 10:37:32 +0000804func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400805 var err error
806 var deviceInfo *oop.DeviceInfo
807
Neha Sharma8f4e4322020-08-06 10:51:53 +0000808 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400809
810 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000811 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400812 }
813 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000814 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400815 }
816
Neha Sharma96b7bf22020-06-15 10:37:32 +0000817 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400818 dh.device.Root = true
819 dh.device.Vendor = deviceInfo.Vendor
820 dh.device.Model = deviceInfo.Model
821 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
822 dh.device.HardwareVersion = deviceInfo.HardwareVersion
823 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
824
825 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000826 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400827 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000828 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400829 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000830 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400831 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000832 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400833 dh.device.MacAddress = genmac
834 } else {
835 dh.device.MacAddress = deviceInfo.DeviceId
836 }
837
838 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000839 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000840 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400841 }
842
843 return deviceInfo, nil
844}
845
Neha Sharma96b7bf22020-06-15 10:37:32 +0000846func startCollector(ctx context.Context, dh *DeviceHandler) {
847 logger.Debugf(ctx, "starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530848 for {
849 select {
850 case <-dh.stopCollector:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000851 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"deviceID:": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530852 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000853 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700854
Neha Sharma8f4e4322020-08-06 10:51:53 +0000855 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400856 if err != nil {
857 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
858 continue
859 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530860 for _, port := range ports {
861 // NNI Stats
862 if port.Type == voltha.Port_ETHERNET_NNI {
863 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
864 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000865 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
866 go dh.portStats.publishMetrics(ctx, cmnni, port, dh.device.Id, dh.device.Type)
867 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530868 }
869 // PON Stats
870 if port.Type == voltha.Port_PON_OLT {
871 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
872 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
873 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000874 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
875 go dh.portStats.publishMetrics(ctx, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530876 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000877 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500878 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530879 }
880 }
881 }
882}
883
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700884//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530885func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400886 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000887 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530888 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530889
890 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400891 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
892 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530893 }
894
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400895 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530896}
897
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700898//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530899func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700900 return &ic.SwitchCapability{
901 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530902 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700903 HwDesc: "open_pon",
904 SwDesc: "open_pon",
905 SerialNum: dh.device.SerialNumber,
906 },
907 SwitchFeatures: &of.OfpSwitchFeatures{
908 NBuffers: 256,
909 NTables: 2,
910 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
911 of.OfpCapabilities_OFPC_TABLE_STATS |
912 of.OfpCapabilities_OFPC_PORT_STATS |
913 of.OfpCapabilities_OFPC_GROUP_STATS),
914 },
915 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530916}
917
Neha Sharma96b7bf22020-06-15 10:37:32 +0000918func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
919 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 -0700920 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700921 var deviceID string
922 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700923
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400924 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700925 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000926 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 -0700927 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
928 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400929
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700930 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530931
932 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
933
Neha Sharma96b7bf22020-06-15 10:37:32 +0000934 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 -0700935 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700936 kwargs := make(map[string]interface{})
937 kwargs["onu_id"] = omciInd.OnuId
938 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700939
Neha Sharma8f4e4322020-08-06 10:51:53 +0000940 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700941 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530942 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700943 "intf-id": omciInd.IntfId,
944 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700945 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700946 deviceType = onuDevice.Type
947 deviceID = onuDevice.Id
948 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
949 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530950 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700951 } else {
952 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +0000953 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 +0530954 deviceType = onuInCache.(*OnuDevice).deviceType
955 deviceID = onuInCache.(*OnuDevice).deviceID
956 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700957 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700958
959 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +0000960 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
Thomas Lee S985938d2020-05-04 11:40:41 +0530961 ic.InterAdapterMessageType_OMCI_REQUEST, dh.device.Type, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530963 return olterrors.NewErrCommunication("omci-request", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530964 "source": dh.device.Type,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800965 "destination": deviceType,
966 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000967 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700968 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800969 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530970}
971
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700972//ProcessInterAdapterMessage sends the proxied messages to the target device
973// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
974// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +0000975func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
976 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700977 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700978 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700979 fromTopic := msg.Header.FromTopic
980 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700981 toDeviceID := msg.Header.ToDeviceId
982 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700983
Neha Sharma96b7bf22020-06-15 10:37:32 +0000984 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 -0700985
986 msgBody := msg.GetBody()
987
988 omciMsg := &ic.InterAdapterOmciMessage{}
989 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000990 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700991 }
992
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700993 if omciMsg.GetProxyAddress() == nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +0000994 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700995 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530996 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800997 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000998 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700999 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001000 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1001 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301002 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001003 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001004 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001005 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001006 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001007 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1008 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301009 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001010 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001011 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001012 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001013 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001014 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001015 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001016 }
1017 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301018}
1019
Neha Sharma96b7bf22020-06-15 10:37:32 +00001020func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021 var intfID uint32
1022 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001023 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001024 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001025 intfID = onuDevice.ProxyAddress.GetChannelId()
1026 onuID = onuDevice.ProxyAddress.GetOnuId()
1027 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001028 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001029 intfID = omciMsg.GetProxyAddress().GetChannelId()
1030 onuID = omciMsg.GetProxyAddress().GetOnuId()
1031 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001032 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001033 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001034 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 -08001035
Thomas Lee S94109f12020-03-03 16:39:29 +05301036 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001037 "intf-id": intfID,
1038 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001039 }
1040
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001041 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1042 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001043 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001044 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1045 hex.Encode(hexPkt, omciMsg.Message)
1046 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1047
1048 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1049 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1050 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001051 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001052 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001053
Neha Sharma8f4e4322020-08-06 10:51:53 +00001054 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001055 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301056 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001057 "intf-id": intfID,
1058 "onu-id": onuID,
1059 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001060 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001061 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001062}
1063
David K. Bainbridge794735f2020-02-11 21:01:37 -08001064func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001065 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 +02001066 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001067 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001068 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001069 // TODO: need resource manager
1070 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001071 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301072 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001073 st, _ := status.FromError(err)
1074 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001075 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1076
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001077 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301078 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001079 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001080 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001081 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001082 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001084}
1085
David K. Bainbridge794735f2020-02-11 21:01:37 -08001086func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001087 channelID := onuDiscInd.GetIntfId()
1088 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001089
Neha Sharma96b7bf22020-06-15 10:37:32 +00001090 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301091
cuilin20187b2a8c32019-03-26 19:52:28 -07001092 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001093 if sn != "" {
1094 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001095 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001096 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001097 }
1098
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301099 var alarmInd oop.OnuAlarmIndication
1100 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001101 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301102
1103 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1104 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1105 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1106 OnuLosRaise event sent for it */
1107 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1108 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1109 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001110 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301111 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1112 "currentIntfId": onuDiscInd.GetIntfId()})
1113 // TODO:: Should we need to ignore raising OnuLosClear event
1114 // when onu connected to different PON?
1115 }
1116 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1117 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1118 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001119 go func() {
1120 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1121 logger.Debugw(ctx, "indication-failed", log.Fields{"error": err})
1122 }
1123 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301124 }
1125 return true
1126 })
1127
Neha Sharma96b7bf22020-06-15 10:37:32 +00001128 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001129 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001130 }
1131
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001132 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001133
1134 // check the ONU is already know to the OLT
1135 // NOTE the second time the ONU is discovered this should return a device
1136 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1137
1138 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001139 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 -08001140 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001141 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 -08001142 switch e.Code() {
1143 case codes.Internal:
1144 // this probably means NOT FOUND, so just create a new device
1145 onuDevice = nil
1146 case codes.DeadlineExceeded:
1147 // if the call times out, cleanup and exit
1148 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001149 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001150 }
1151 }
1152 }
1153
1154 if onuDevice == nil {
1155 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001156 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001157 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001158 ponintfid := onuDiscInd.GetIntfId()
1159 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301160 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001161 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001162
Neha Sharma96b7bf22020-06-15 10:37:32 +00001163 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001164
1165 if err != nil {
1166 // if we can't create an ID in resource manager,
1167 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001168 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001169 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001170 "pon-intf-id": ponintfid,
1171 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001172 }
1173
Neha Sharma8f4e4322020-08-06 10:51:53 +00001174 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001175 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001176 dh.discOnus.Delete(sn)
1177 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 +05301178 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001179 "pon-intf-id": ponintfid,
1180 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001181 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04001182 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano()); err != nil {
1183 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"error": err})
1184 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001185 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301186 log.Fields{"onuDevice": onuDevice,
1187 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001188 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301189 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001190 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001191
1192 // we can now use the existing ONU Id
1193 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001194 //Insert the ONU into cache to use in OnuIndication.
1195 //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 +00001196 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001197 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301198 "intfId": onuDiscInd.GetIntfId(),
1199 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001200 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001201
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301202 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301203 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001204 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301205 log.Fields{"onu": onuDev,
1206 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001207
Kent Hagermane6ff1012020-07-14 15:07:53 -04001208 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301209 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001211 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001212 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001213 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001214 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301215 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001216 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001217 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 }
1219 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001220}
1221
Neha Sharma96b7bf22020-06-15 10:37:32 +00001222func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001223 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1224
1225 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001226 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001227 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001228 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001229 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001230 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301231 log.Fields{"onuId": onuInd.OnuId,
1232 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301233 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001234 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301235
David K. Bainbridge794735f2020-02-11 21:01:37 -08001236 errFields := log.Fields{"device-id": dh.device.Id}
1237
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301238 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1239
Mahir Gunyele77977b2019-06-27 05:36:22 -07001240 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1241 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001242 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001243 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001244 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001245 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1246 if serialNumber != "" {
1247 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001248 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001249 } else {
1250 kwargs["onu_id"] = onuInd.OnuId
1251 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 errFields["onu-id"] = onuInd.OnuId
1253 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001254 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001255 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001256 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001257
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001259 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001260 }
1261
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001263 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264 "previousIntfId": onuDevice.ParentPortNo,
1265 "currentIntfId": ponPort})
1266 }
1267
1268 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001269 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301270 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1271 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301272 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001273 }
1274 if !foundInCache {
1275 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1276
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301277 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 -08001278
1279 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001280 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001281 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282 }
1283 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001284}
1285
Neha Sharma96b7bf22020-06-15 10:37:32 +00001286func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001287 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 -07001288 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1289 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1290 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1291 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001292 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001293 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1294 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001295 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001296 onuInd.OperState = "down"
1297 }
1298 }
1299
David K. Bainbridge794735f2020-02-11 21:01:37 -08001300 switch onuInd.OperState {
1301 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001302 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 -07001303 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301304 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001305 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1306 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301307 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 "onu-indicator": onuInd,
1309 "source": "openolt",
1310 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001311 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001312 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001313 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001314 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 -04001315 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301316 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1318 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301319 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001320 "onu-indicator": onuInd,
1321 "source": "openolt",
1322 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001323 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001324 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001325 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001326 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001327 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001328 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001329}
1330
cuilin20187b2a8c32019-03-26 19:52:28 -07001331func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1332 if serialNum != nil {
1333 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001334 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001335 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001336}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001337func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1338 decodedStr, err := hex.DecodeString(serialNum[4:])
1339 if err != nil {
1340 return nil, err
1341 }
1342 return &oop.SerialNumber{
1343 VendorId: []byte(serialNum[:4]),
1344 VendorSpecific: []byte(decodedStr),
1345 }, nil
1346}
cuilin20187b2a8c32019-03-26 19:52:28 -07001347
1348func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1349 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001350 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001351 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1352 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1353 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1354 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1355 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1356 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1357 return tmp
1358}
1359
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001360//UpdateFlowsBulk upates the bulk flow
1361func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301362 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001363}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001364
1365//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001366func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1367 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301368 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001369 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301370 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001371 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001372 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001373 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001374 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001375 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001376 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001377 "intf-id": parentPort,
1378 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001379 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001380 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 -08001381 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301382}
1383
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001384// SendPacketInToCore sends packet-in to core
1385// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1386// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001388 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001389 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001390 "port": logicalPort,
1391 "packet": hex.EncodeToString(packetPayload),
1392 "device-id": dh.device.Id,
1393 })
1394 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001395 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 +05301396 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397 "source": "adapter",
1398 "destination": "core",
1399 "device-id": dh.device.Id,
1400 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001401 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001402 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001403 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001404 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001405 "packet": hex.EncodeToString(packetPayload),
1406 "device-id": dh.device.Id,
1407 })
1408 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001409 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001410}
1411
A R Karthick1f85b802019-10-11 05:06:05 +00001412// AddUniPortToOnu adds the uni port to the onu device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001413func (dh *DeviceHandler) AddUniPortToOnu(ctx context.Context, intfID, onuID, uniPort uint32) {
A R Karthick1f85b802019-10-11 05:06:05 +00001414 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301415
1416 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001417 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301418 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1419 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001420 logger.Debugw(ctx, "adding-uni-port", log.Fields{"port": uniPort, "intf-id": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001421 }
1422 }
1423}
1424
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001425// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001426func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001427 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001428
1429 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1430 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001431 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001432 }
1433
Kent Hagermane6ff1012020-07-14 15:07:53 -04001434 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001435 metrics := dh.metrics.GetSubscriberMetrics()
1436 for _, m := range pmConfigs.Metrics {
1437 metrics[m.Name].Enabled = m.Enabled
1438
1439 }
1440 }
1441}
1442
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001443//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301444func (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 +00001445 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 +01001446
1447 var errorsList []error
1448
Girish Gowdru0c588b22019-04-23 23:24:56 -04001449 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001450 for _, flow := range flows.ToRemove.Items {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001451 dh.incrementActiveFlowRemoveCount(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001452
Neha Sharma96b7bf22020-06-15 10:37:32 +00001453 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301454 log.Fields{"device-id": device.Id,
1455 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001456 err := dh.flowMgr.RemoveFlow(ctx, flow)
1457 if err != nil {
1458 errorsList = append(errorsList, err)
1459 }
1460
Neha Sharma96b7bf22020-06-15 10:37:32 +00001461 dh.decrementActiveFlowRemoveCount(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001462 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301463
1464 for _, flow := range flows.ToAdd.Items {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001465 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301466 log.Fields{"device-id": device.Id,
1467 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001468 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
Neha Sharma96b7bf22020-06-15 10:37:32 +00001469 dh.waitForFlowRemoveToFinish(ctx, flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001470 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1471 if err != nil {
1472 errorsList = append(errorsList, err)
1473 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301474 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001475 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001476
Girish Gowdracefae192020-03-19 18:14:10 -07001477 // 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 +00001478 if groups != nil {
1479 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001480 err := dh.flowMgr.AddGroup(ctx, group)
1481 if err != nil {
1482 errorsList = append(errorsList, err)
1483 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001484 }
1485 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001486 err := dh.flowMgr.ModifyGroup(ctx, group)
1487 if err != nil {
1488 errorsList = append(errorsList, err)
1489 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001490 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001491 for _, group := range groups.ToRemove.Items {
1492 err := dh.flowMgr.DeleteGroup(ctx, group)
1493 if err != nil {
1494 errorsList = append(errorsList, err)
1495 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001496 }
1497 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001498 if len(errorsList) > 0 {
1499 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1500 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001501 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001502 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301503}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001504
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001505//DisableDevice disables the given device
1506//It marks the following for the given device:
1507//Device-Handler Admin-State : down
1508//Device Port-State: UNKNOWN
1509//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001510func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001511 /* On device disable ,admin state update has to be done prior sending request to agent since
1512 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001513 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001514 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001515 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001516 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001517 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001518 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001519 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001520 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001521 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001522 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301523
1524 dh.discOnus = sync.Map{}
1525 dh.onus = sync.Map{}
1526
Thomas Lee S85f37312020-04-03 17:06:12 +05301527 //stopping the stats collector
1528 dh.stopCollector <- true
1529
Neha Sharma96b7bf22020-06-15 10:37:32 +00001530 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001531 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301532 //Update device Admin state
1533 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001534 // 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 +00001535 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 -04001536 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001537 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001538 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001539 return nil
1540}
1541
Neha Sharma96b7bf22020-06-15 10:37:32 +00001542func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001543 // Update onu state as unreachable in onu adapter
1544 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301545 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001546 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001547 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001548 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001549 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 -04001550 }
1551 if onuDevices != nil {
1552 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001553 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001554 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1555 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001556 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301557 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001558 }
1559
1560 }
1561 }
1562
1563}
1564
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001565//ReenableDevice re-enables the olt device after disable
1566//It marks the following for the given device:
1567//Device-Handler Admin-State : up
1568//Device Port-State: ACTIVE
1569//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001571 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301572 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001573 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301574 }
1575 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001576 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001577
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001578 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001579
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001580 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1581 if err != nil {
1582 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device": device.Id}, err)
1583 }
1584 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001585 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001586 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001587 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001588 device.OperStatus = voltha.OperStatus_ACTIVE
1589 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001590
Neha Sharma8f4e4322020-08-06 10:51:53 +00001591 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 +05301592 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001593 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001594 "connect-status": device.ConnectStatus,
1595 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001596 }
kesavand39e0aa32020-01-28 20:58:50 -05001597
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001599
1600 return nil
1601}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001602
npujarec5762e2020-01-01 14:08:48 +05301603func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001604 var uniID uint32
1605 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301606 for _, port := range onu.UniPorts {
1607 uniID = UniIDFromPortNum(uint32(port))
Neha Sharma96b7bf22020-06-15 10:37:32 +00001608 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001609 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301610 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001611 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001612 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001613 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301614 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001615 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301616 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001617 }
npujarec5762e2020-01-01 14:08:48 +05301618 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001619 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301620 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001621 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001622 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001623 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301624 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001625 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001626 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001627 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301628 }
npujarec5762e2020-01-01 14:08:48 +05301629 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1630 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001631 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301632 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001633 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Esin Karaman7fb80c22020-07-16 14:23:33 +00001634 if err = dh.resourceMgr.DelGemPortPktInOfAllServices(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001635 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 +00001636 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001637 }
1638 return nil
1639}
1640
npujarec5762e2020-01-01 14:08:48 +05301641func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001642 nniUniID := -1
1643 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301644
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001645 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301646 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001647 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001648 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301649 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301650 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001651 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001652 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001653 logger.Debugw(ctx, "nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301654 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301655 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +00001656 logger.Debugw(ctx, "current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301657 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301658 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301659 }
npujarec5762e2020-01-01 14:08:48 +05301660 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001661 }
npujarec5762e2020-01-01 14:08:48 +05301662 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001663 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301664 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001666}
1667
1668// 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 +05301669func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001670 logger.Debug(ctx, "function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001671 /* Clear the KV store data associated with the all the UNI ports
1672 This clears up flow data and also resource map data for various
1673 other pon resources like alloc_id and gemport_id
1674 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001675 go dh.cleanupDeviceResources(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001676 logger.Debug(ctx, "removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001677 // Stop the Stats collector
1678 dh.stopCollector <- true
1679 // stop the heartbeat check routine
1680 dh.stopHeartbeatCheck <- true
1681 //Reset the state
1682 if dh.Client != nil {
1683 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301684 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001685 }
1686 }
1687 cloned := proto.Clone(device).(*voltha.Device)
1688 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1689 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1690 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1691 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1692 "device-id": device.Id,
1693 "connect-status": cloned.ConnectStatus,
1694 "oper-status": cloned.OperStatus}, err).Log()
1695 }
1696 return nil
1697}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001698func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001699
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001700 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301701 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1702 var ponPort uint32
1703 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1704 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301705 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301706 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001707 _ = olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001708 "device-id": dh.device.Id,
Kent Hagermane6ff1012020-07-14 15:07:53 -04001709 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301710 }
1711 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301712 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001713 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301714 if err = dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001715 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301716 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301717 // Clear flowids for gem cache.
1718 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301719 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301720 }
1721 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301722 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301723 }
npujarec5762e2020-01-01 14:08:48 +05301724 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301725 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301726 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301727 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001728 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001729 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001730 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001731 /* Clear the flows from KV store associated with NNI port.
1732 There are mostly trap rules from NNI port (like LLDP)
1733 */
npujarec5762e2020-01-01 14:08:48 +05301734 if err := dh.clearNNIData(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001735 logger.Errorw(ctx, "failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001736 }
A R Karthick1f85b802019-10-11 05:06:05 +00001737
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001738 /* Clear the resource pool for each PON port in the background */
Kent Hagermane6ff1012020-07-14 15:07:53 -04001739 go func() {
1740 if err := dh.resourceMgr.Delete(ctx); err != nil {
1741 logger.Debug(ctx, err)
1742 }
1743 }()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001744 }
A R Karthick1f85b802019-10-11 05:06:05 +00001745
Devmalya Paul495b94a2019-08-27 19:42:00 -04001746 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301747 dh.onus.Range(func(key interface{}, value interface{}) bool {
1748 dh.onus.Delete(key)
1749 return true
1750 })
1751
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001752 /*Delete discovered ONU map for the device*/
1753 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1754 dh.discOnus.Delete(key)
1755 return true
1756 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001757}
1758
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001759//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001760func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001761 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301762 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001763 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001764 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001765 return nil
1766}
1767
David K. Bainbridge794735f2020-02-11 21:01:37 -08001768func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001769 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001770 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001771 "packet-indication": *packetIn,
1772 "device-id": dh.device.Id,
1773 "packet": hex.EncodeToString(packetIn.Pkt),
1774 })
1775 }
npujarec5762e2020-01-01 14:08:48 +05301776 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001777 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001778 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001779 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001780 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001781 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001782 "logical-port-num": logicalPortNum,
1783 "device-id": dh.device.Id,
1784 "packet": hex.EncodeToString(packetIn.Pkt),
1785 })
1786 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001787
Neha Sharma8f4e4322020-08-06 10:51:53 +00001788 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 +05301789 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001790 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301791 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001792 "device-id": dh.device.Id,
1793 "packet": hex.EncodeToString(packetIn.Pkt),
1794 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001795 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001796
Matteo Scandolo92186242020-06-12 10:54:18 -07001797 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001798 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001799 "packet": hex.EncodeToString(packetIn.Pkt),
1800 "device-id": dh.device.Id,
1801 })
1802 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001803 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001804}
1805
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001806// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301807func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001808 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001809 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001810 "device-id": dh.device.Id,
1811 "egress-port-no": egressPortNo,
1812 "pkt-length": len(packet.Data),
1813 "packet": hex.EncodeToString(packet.Data),
1814 })
1815 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001816
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001817 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001818 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001819 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1820 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301821 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1822 // Do not packet-out lldp packets on uni port.
1823 // ONOS has no clue about uni/nni ports, it just packets out on all
1824 // available ports on the Logical Switch. It should not be interested
1825 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001826 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001827 "device-id": dh.device.Id,
1828 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301829 return nil
1830 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001831 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1832 if innerEthType == 0x8100 {
1833 // q-in-q 802.1ad or 802.1q double tagged packet.
1834 // slice out the outer tag.
1835 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001836 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001837 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001838 "packet-data": hex.EncodeToString(packet.Data),
1839 "device-id": dh.device.Id,
1840 })
1841 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001842 }
1843 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001844 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1845 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001846 uniID := UniIDFromPortNum(uint32(egressPortNo))
1847
Esin Karaman7fb80c22020-07-16 14:23:33 +00001848 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001849 if err != nil {
1850 // In this case the openolt agent will receive the gemPortID as 0.
1851 // The agent tries to retrieve the gemPortID in this case.
1852 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001853 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001854 "intf-id": intfID,
1855 "onu-id": onuID,
1856 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001857 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301858 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001859 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001860 }
1861
1862 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001863
Matteo Scandolo92186242020-06-12 10:54:18 -07001864 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001865 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001866 "egress-port-no": egressPortNo,
1867 "intf-id": intfID,
1868 "onu-id": onuID,
1869 "uni-id": uniID,
1870 "gem-port-id": gemPortID,
1871 "packet": hex.EncodeToString(packet.Data),
1872 "device-id": dh.device.Id,
1873 })
1874 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001875
npujarec5762e2020-01-01 14:08:48 +05301876 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301877 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001878 "source": "adapter",
1879 "destination": "onu",
1880 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001881 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001882 "oni-id": onuID,
1883 "uni-id": uniID,
1884 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001885 "packet": hex.EncodeToString(packet.Data),
1886 "device-id": dh.device.Id,
1887 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001888 }
1889 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001890 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001891 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001892 return olterrors.NewErrInvalidValue(log.Fields{
1893 "egress-nni-port": egressPortNo,
1894 "device-id": dh.device.Id,
1895 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001896 }
1897 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001898
Matteo Scandolo92186242020-06-12 10:54:18 -07001899 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001900 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001901 "uplink-pkt": uplinkPkt,
1902 "packet": hex.EncodeToString(packet.Data),
1903 "device-id": dh.device.Id,
1904 })
1905 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001906
npujarec5762e2020-01-01 14:08:48 +05301907 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001908 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1909 "packet": hex.EncodeToString(packet.Data),
1910 "device-id": dh.device.Id,
1911 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001912 }
1913 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001914 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301915 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001916 "egressPortType": egressPortType,
1917 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301918 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001919 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001920 }
1921 return nil
1922}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001923
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001924func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1925 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001926}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301927
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001928func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001929
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301930 // start the heartbeat check towards the OLT.
1931 var timerCheck *time.Timer
1932
1933 for {
1934 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1935 select {
1936 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00001937 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001938 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001939 logger.Warnw(ctx, "hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301940 if timerCheck == nil {
1941 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001942 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301943 }
1944 } else {
1945 if timerCheck != nil {
1946 if timerCheck.Stop() {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001947 logger.Debugw(ctx, "got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301948 }
1949 timerCheck = nil
1950 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001951 logger.Debugw(ctx, "hearbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05301952 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301953 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301954 }
1955 cancel()
1956 case <-dh.stopHeartbeatCheck:
Neha Sharma96b7bf22020-06-15 10:37:32 +00001957 logger.Debugw(ctx, "stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301958 return
1959 }
1960 }
1961}
1962
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001963func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1964 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1965 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001966 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001967 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301968
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001969 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1970 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001971 _ = 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 -04001972 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001973 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001974 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001975 }
1976 go dh.cleanupDeviceResources(ctx)
1977
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001978 dh.lockDevice.RLock()
1979 // Stop the read indication only if it the routine is active
1980 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1981 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1982 // on next execution of the readIndication routine.
1983 if dh.isReadIndicationRoutineActive {
1984 dh.stopIndications <- true
1985 }
1986 dh.lockDevice.RUnlock()
1987
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001988 dh.transitionMap.Handle(ctx, DeviceInit)
1989
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301990 }
1991}
kesavand39e0aa32020-01-28 20:58:50 -05001992
1993// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00001994func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
1995 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
1996 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001997}
1998
1999// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002000func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2001 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2002 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002003}
2004
kdarapu1afeceb2020-02-12 01:38:09 -05002005//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 +00002006func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2007 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002008 if port.GetType() == voltha.Port_ETHERNET_NNI {
2009 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002010 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302011 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302012 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002013 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002014 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002015 }
2016 // fetch interfaceid from PortNo
2017 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2018 ponIntf := &oop.Interface{IntfId: ponID}
2019 var operStatus voltha.OperStatus_Types
2020 if enablePort {
2021 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302022 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002023
2024 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302025 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002026 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002027 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002028 }
2029 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002030 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002031 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002032 } else {
2033 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302034 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002035 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302036 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002037 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002038 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002039 }
2040 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002041 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002042 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002043 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302044 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 +05302045 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302046 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002047 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002048 }
2049 return nil
2050}
2051
kdarapu1afeceb2020-02-12 01:38:09 -05002052//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002053func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002054 // Disable the port and update the oper_port_status to core
2055 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002056 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002057 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002058 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302059 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302060 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002061 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002062 }
2063 }
2064 }
2065 return nil
2066}
2067
2068//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002069func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2070 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2071 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002072 if port.Type == voltha.Port_ETHERNET_NNI {
2073 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002074 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002075 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002076 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002077 }
2078 }
2079 if port.Type == voltha.Port_PON_OLT {
2080 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002081 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002082 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002083 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002084 }
2085 }
2086 }
2087}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002088
2089// ChildDeviceLost deletes ONU and clears pon resources related to it.
2090func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002091 logger.Debugw(ctx, "child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002092 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2093 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002094 onuDevice, ok := dh.onus.Load(onuKey)
2095 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302096 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002097 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002098 "device-id": dh.device.Id,
2099 "onu-id": onuID,
2100 "intf-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002101 }
2102 var sn *oop.SerialNumber
2103 var err error
2104 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302105 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002106 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302107 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002108 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2109 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002110
2111 for uniID := 0; uniID < MaxUnisPerOnu; uniID++ {
2112 var flowRemoveData pendingFlowRemoveData
2113 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uint32(uniID)}
2114 dh.lockDevice.RLock()
2115 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2116 dh.lockDevice.RUnlock()
2117 continue
2118 }
2119 dh.lockDevice.RUnlock()
2120
2121 log.Debugw("wait-for-flow-remove-complete-before-processing-child-device-lost",
2122 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2123 // Wait for all flow removes to finish first
2124 <-flowRemoveData.allFlowsRemoved
2125 log.Debugw("flow-removes-complete-for-subscriber",
2126 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2127 }
2128
2129 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Neha Sharma8f4e4322020-08-06 10:51:53 +00002130 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302131 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302132 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002133 "onu-id": onuID}, err).Log()
2134 }
2135 //clear PON resources associated with ONU
2136 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002137 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002138 logger.Warnw(ctx, "failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002139 "device-id": dh.device.Id,
2140 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002141 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002142 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002143 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002144 "device-id": dh.device.Id,
2145 "intf-id": intfID,
2146 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002147 } else {
2148 for i, onu := range onuGemData {
2149 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002150 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002151 if err := dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002152 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302153 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002154 "onu-device": onu,
2155 "error": err})
2156 }
2157 // Clear flowids for gem cache.
2158 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002159 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002160 }
2161 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002162 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002163 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002164 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002165 "intf-id": intfID,
2166 "onu-device": onu,
2167 "onu-gem": onuGemData,
2168 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002169 //Not returning error on cleanup.
2170 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002171 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002172 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002173 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002174 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002175 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002176 }
2177 }
2178 dh.onus.Delete(onuKey)
2179 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2180 return nil
2181}
Girish Gowdracefae192020-03-19 18:14:10 -07002182
2183func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2184 for _, field := range flows.GetOfbFields(flow) {
2185 if field.Type == flows.IN_PORT {
2186 return field.GetPort()
2187 }
2188 }
2189 return InvalidPort
2190}
2191
2192func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2193 for _, action := range flows.GetActions(flow) {
2194 if action.Type == flows.OUTPUT {
2195 if out := action.GetOutput(); out != nil {
2196 return out.GetPort()
2197 }
2198 }
2199 }
2200 return InvalidPort
2201}
2202
Neha Sharma96b7bf22020-06-15 10:37:32 +00002203func (dh *DeviceHandler) incrementActiveFlowRemoveCount(ctx context.Context, flow *of.OfpFlowStats) {
Girish Gowdracefae192020-03-19 18:14:10 -07002204 inPort, outPort := getPorts(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002205 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 -07002206 if inPort != InvalidPort && outPort != InvalidPort {
2207 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2208 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002209 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 -07002210
2211 dh.lockDevice.Lock()
2212 defer dh.lockDevice.Unlock()
2213 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2214 if !ok {
2215 flowRemoveData = pendingFlowRemoveData{
2216 pendingFlowRemoveCount: 0,
2217 allFlowsRemoved: make(chan struct{}),
2218 }
2219 }
2220 flowRemoveData.pendingFlowRemoveCount++
2221 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2222
Neha Sharma96b7bf22020-06-15 10:37:32 +00002223 logger.Debugw(ctx, "current-flow-remove-count–increment",
Matteo Scandolo92186242020-06-12 10:54:18 -07002224 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
Girish Gowdracefae192020-03-19 18:14:10 -07002225 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2226 }
2227}
2228
Neha Sharma96b7bf22020-06-15 10:37:32 +00002229func (dh *DeviceHandler) decrementActiveFlowRemoveCount(ctx context.Context, flow *of.OfpFlowStats) {
Girish Gowdracefae192020-03-19 18:14:10 -07002230 inPort, outPort := getPorts(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002231 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 -07002232 if inPort != InvalidPort && outPort != InvalidPort {
2233 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2234 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002235 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 -07002236
2237 dh.lockDevice.Lock()
2238 defer dh.lockDevice.Unlock()
2239 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002240 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 -07002241 } else {
2242 if val.pendingFlowRemoveCount > 0 {
2243 val.pendingFlowRemoveCount--
2244 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002245 logger.Debugw(ctx, "current-flow-remove-count-after-decrement",
Matteo Scandolo92186242020-06-12 10:54:18 -07002246 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
Girish Gowdracefae192020-03-19 18:14:10 -07002247 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2248 // If all flow removes have finished, then close the channel to signal the receiver
2249 // to go ahead with flow adds.
2250 if val.pendingFlowRemoveCount == 0 {
2251 close(val.allFlowsRemoved)
2252 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2253 return
2254 }
2255 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2256 }
2257 }
2258}
2259
Neha Sharma96b7bf22020-06-15 10:37:32 +00002260func (dh *DeviceHandler) waitForFlowRemoveToFinish(ctx context.Context, flow *of.OfpFlowStats) {
Girish Gowdracefae192020-03-19 18:14:10 -07002261 var flowRemoveData pendingFlowRemoveData
2262 var ok bool
2263 inPort, outPort := getPorts(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002264 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 -07002265 if inPort != InvalidPort && outPort != InvalidPort {
2266 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2267 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002268 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 -07002269
2270 dh.lockDevice.RLock()
2271 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002272 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 -07002273 dh.lockDevice.RUnlock()
2274 return
2275 }
2276 dh.lockDevice.RUnlock()
2277
2278 // Wait for all flow removes to finish first
2279 <-flowRemoveData.allFlowsRemoved
2280
Neha Sharma96b7bf22020-06-15 10:37:32 +00002281 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 -07002282 }
2283}
2284
2285func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2286 inPort := getInPortFromFlow(flow)
2287 outPort := getOutPortFromFlow(flow)
2288
2289 if inPort == InvalidPort || outPort == InvalidPort {
2290 return inPort, outPort
2291 }
2292
2293 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2294 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2295 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2296 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2297 return uniPort, outPort
2298 }
2299 }
2300 } else {
2301 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2302 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2303 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2304 return inPort, uniPort
2305 }
2306 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2307 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2308 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2309 return uniPort, outPort
2310 }
2311 }
2312 }
2313
2314 return InvalidPort, InvalidPort
2315}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002316
2317func extractOmciTransactionID(omciPkt []byte) uint16 {
2318 if len(omciPkt) > 3 {
2319 d := omciPkt[0:2]
2320 transid := binary.BigEndian.Uint16(d)
2321 return transid
2322 }
2323 return 0
2324}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002325
2326// StoreOnuDevice stores the onu parameters to the local cache.
2327func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2328 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2329 dh.onus.Store(onuKey, onuDevice)
2330}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002331
Neha Sharma8f4e4322020-08-06 10:51:53 +00002332func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002333 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002334 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002335 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002336 resp := new(voltha.ReturnValues)
2337 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002338 ctx = log.WithSpanFromContext(context.Background(), ctx)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002339 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002340 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2341 return nil, err
2342 }
2343 ID = device.ProxyAddress.GetOnuId()
2344 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2345 valueparam.Onu = &Onu
2346 valueparam.Value = value
2347
2348 // This API is unsupported until agent patch is added
2349 resp.Unsupported = uint32(value)
2350 _ = ctx
2351
2352 // Uncomment this code once agent changes are complete and tests
2353 /*
2354 resp, err = dh.Client.GetValue(ctx, valueparam)
2355 if err != nil {
2356 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2357 return nil, err
2358 }
2359 */
2360
2361 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2362 return resp, nil
2363}