blob: 7c7dc06a8fdcb656a228c868a6f591667ba3372a [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
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530118 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400119 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700120}
121
Naga Manjunath7615e552019-10-11 22:35:47 +0530122var pmNames = []string{
123 "rx_bytes",
124 "rx_packets",
125 "rx_mcast_packets",
126 "rx_bcast_packets",
127 "tx_bytes",
128 "tx_packets",
129 "tx_mcast_packets",
130 "tx_bcast_packets",
131}
132
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700133//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530134func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700135 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700136 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700137 device.deviceType = deviceTp
138 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700139 device.onuID = onuID
140 device.intfID = intfID
141 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530142 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700143 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530144}
145
146//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530147func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700148 var dh DeviceHandler
149 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400150 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400151 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700152 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700153 dh.device = cloned
154 dh.openOLT = adapter
155 dh.exitChannel = make(chan int, 1)
156 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530157 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530158 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530159 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 -0500160 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400161 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700162 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
163
cuilin20187b2a8c32019-03-26 19:52:28 -0700164 //TODO initialize the support classes.
165 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530166}
167
168// start save the device to the data model
169func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700170 dh.lockDevice.Lock()
171 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000172 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700173 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000174 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530175}
176
177// stop stops the device dh. Not much to do for now
178func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700179 dh.lockDevice.Lock()
180 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000181 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700182 dh.exitChannel <- 1
Neha Sharma96b7bf22020-06-15 10:37:32 +0000183 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530184}
185
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400186func macifyIP(ip net.IP) string {
187 if len(ip) > 0 {
188 oct1 := strconv.FormatInt(int64(ip[12]), 16)
189 oct2 := strconv.FormatInt(int64(ip[13]), 16)
190 oct3 := strconv.FormatInt(int64(ip[14]), 16)
191 oct4 := strconv.FormatInt(int64(ip[15]), 16)
192 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
193 }
194 return ""
195}
196
Neha Sharma96b7bf22020-06-15 10:37:32 +0000197func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400198 var genmac string
199 var addr net.IP
200 var ips []string
201 var err error
202
Neha Sharma96b7bf22020-06-15 10:37:32 +0000203 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400204
205 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000206 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400207
208 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000209 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400210 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000211 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400212 }
213 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000214 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530215 log.Fields{"host": ips[0],
216 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400217 return genmac, nil
218 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000219 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400220 }
221
222 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000223 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530224 log.Fields{"host": host,
225 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400226 return genmac, nil
227}
228
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530229func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700230 slist := strings.Split(mac, ":")
231 result := make([]uint32, len(slist))
232 var err error
233 var tmp int64
234 for index, val := range slist {
235 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
236 return []uint32{1, 2, 3, 4, 5, 6}
237 }
238 result[index] = uint32(tmp)
239 }
240 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530241}
242
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700243//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 -0800244func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530245
David K. Bainbridge794735f2020-02-11 21:01:37 -0800246 switch portType {
247 case voltha.Port_ETHERNET_NNI:
248 return fmt.Sprintf("nni-%d", portNum), nil
249 case voltha.Port_PON_OLT:
250 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700251 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800252
Girish Kumarf26e4882020-03-05 06:49:10 +0000253 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530254}
255
Neha Sharma96b7bf22020-06-15 10:37:32 +0000256func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000257 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700258 if state == "up" {
259 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500260 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500261 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700262 } else {
263 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500264 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700265 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700266 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400267 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800268 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000269 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400270 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500271
Neha Sharma8f4e4322020-08-06 10:51:53 +0000272 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 -0400273 log.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
Neha Sharma8f4e4322020-08-06 10:51:53 +0000274 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 -0400275 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
276 "device-id": dh.device.Id,
277 "port-type": portType,
278 "port-number": portNum,
279 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500280 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400281 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500282 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400283 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700284 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400285 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700286 PortNo: portNum,
287 Label: label,
288 Type: portType,
289 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700290 OfpPort: &of.OfpPort{
291 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
292 Config: 0,
293 State: uint32(of.OfpPortState_OFPPS_LIVE),
294 Curr: capacity,
295 Advertised: capacity,
296 Peer: capacity,
297 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
298 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
299 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700300 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000301 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700302 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000303 if err := dh.coreProxy.PortCreated(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000304 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800305 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000306 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400307 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000308 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530309 return nil
310}
311
Kent Hagermane6ff1012020-07-14 15:07:53 -0400312func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530313 dh.lockDevice.Lock()
314 defer dh.lockDevice.Unlock()
Neha Sharma8f4e4322020-08-06 10:51:53 +0000315 device, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530316 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400317 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
318 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530319 }
320 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530321}
322
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700323// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530324// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800325func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000326 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700327 defer func() {
328 dh.lockDevice.Lock()
329 dh.isReadIndicationRoutineActive = false
330 dh.lockDevice.Unlock()
331 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700332 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700333 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700334 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700335 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400336 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530337 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400338 if err != nil || device == nil {
339 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000340 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400341 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400342
David Bainbridgef5879ca2019-12-13 21:17:54 +0000343 // Create an exponential backoff around re-enabling indications. The
344 // maximum elapsed time for the back off is set to 0 so that we will
345 // continue to retry. The max interval defaults to 1m, but is set
346 // here for code clarity
347 indicationBackoff := backoff.NewExponentialBackOff()
348 indicationBackoff.MaxElapsedTime = 0
349 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700350
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700351 dh.lockDevice.Lock()
352 dh.isReadIndicationRoutineActive = true
353 dh.lockDevice.Unlock()
354
Girish Gowdra3f974912020-03-23 20:35:18 -0700355Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700356 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400357 select {
358 case <-dh.stopIndications:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000359 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700360 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400361 default:
362 indication, err := indications.Recv()
363 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000364 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530365 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530366 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400367 // Use an exponential back off to prevent getting into a tight loop
368 duration := indicationBackoff.NextBackOff()
369 if duration == backoff.Stop {
370 // If we reach a maximum then warn and reset the backoff
371 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000372 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530373 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530374 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400375 indicationBackoff.Reset()
376 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700377
378 // On failure process a backoff timer while watching for stopIndications
379 // events
380 backoff := time.NewTimer(indicationBackoff.NextBackOff())
381 select {
382 case <-dh.stopIndications:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000383 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700384 if !backoff.Stop() {
385 <-backoff.C
386 }
387 break Loop
388 case <-backoff.C:
389 // backoff expired continue
390 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700391 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
392 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400393 }
394 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000395 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530396 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000397 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530398 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530399 "device-id": dh.device.Id})
400 if device.AdminState == voltha.AdminState_DELETED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000401 logger.Debug(ctx, "device-deleted--stopping-the-read-indication-thread")
Girish Gowdra3f974912020-03-23 20:35:18 -0700402 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400403 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700404 // Close the stream, and re-initialize it
405 if err = indications.CloseSend(); err != nil {
406 // Ok to ignore here, because we landed here due to a problem on the stream
407 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000408 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530409 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530410 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700411 }
412 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
413 return err
414 }
415 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400416 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530417 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400418 // Reset backoff if we have a successful receive
419 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400420 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530421 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000422 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530423 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530424 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400425 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400426 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400427 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700428 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700429 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700430 // Close the send stream
431 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700432
Girish Gowdra3f974912020-03-23 20:35:18 -0700433 return nil
434}
435
436func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
437
438 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
439 if err != nil {
440 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
441 }
442 if indications == nil {
443 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
444 }
445
446 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400447}
448
449// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
450func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
451 switch indication.Data.(type) {
452 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
453 return true
454
455 default:
456 return false
457 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700458}
459
David K. Bainbridge794735f2020-02-11 21:01:37 -0800460func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000461 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000462 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530463 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700464 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530465 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700466 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000467 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000468 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530469 return olterrors.NewErrAdapter("failed-indication", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530470 "device_id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800471 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000472 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800473 }
474 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700475}
476
David K. Bainbridge794735f2020-02-11 21:01:37 -0800477// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530478func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400479 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700480 switch indication.Data.(type) {
481 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000482 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
483 defer span.Finish()
484
David K. Bainbridge794735f2020-02-11 21:01:37 -0800485 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400486 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700488 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000489 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
490 defer span.Finish()
491
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700492 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800493 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000494 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400495 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800496 }
497 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000498 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700499 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000500 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
501 defer span.Finish()
502
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700503 intfOperInd := indication.GetIntfOperInd()
504 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800505 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000506 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400507 _ = 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 -0800508 }
509 }()
Kent Hagermane6ff1012020-07-14 15:07:53 -0400510 if err := dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId()); err != nil {
511 logger.Warn(ctx, err)
512 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700513 } else if intfOperInd.GetType() == "pon" {
514 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
515 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800516 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000517 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400518 _ = 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 -0800519 }
520 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000521 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700522 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000523 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530524 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530525 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700526 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000527 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
528 defer span.Finish()
529
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700530 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000531 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700532 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800533 go func() {
534 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400535 _ = 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 -0800536 }
537 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700538 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000539 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
540 defer span.Finish()
541
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700542 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000543 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800544 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000545 if err := dh.onuIndication(ctx, onuInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400546 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800547 }
548 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700549 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000550 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
551 defer span.Finish()
552
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700553 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000554 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 -0800555 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000556 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400557 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800558 }
559 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700560 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000561 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
562 defer span.Finish()
563
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700564 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000565 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700566 "intf-type": pktInd.IntfId,
567 "intf-id": pktInd.IntfId,
568 "gem-port-id": pktInd.GemportId,
569 "port-no": pktInd.PortNo,
570 "device-id": dh.device.Id,
571 })
572
573 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000574 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700575 "intf-type": pktInd.IntfId,
576 "intf-id": pktInd.IntfId,
577 "gem-port-id": pktInd.GemportId,
578 "port-no": pktInd.PortNo,
579 "packet": hex.EncodeToString(pktInd.Pkt),
580 "device-id": dh.device.Id,
581 })
582 }
583
David K. Bainbridge794735f2020-02-11 21:01:37 -0800584 go func() {
585 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400586 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800587 }
588 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700589 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000590 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
591 defer span.Finish()
592
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700593 portStats := indication.GetPortStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000594 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700595 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000596 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
597 defer span.Finish()
598
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700599 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000600 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700601 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000602 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
603 defer span.Finish()
604
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700605 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000606 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
607 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700608 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530609}
610
611// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530612func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530613 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000614 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530615
Girish Gowdru0c588b22019-04-23 23:24:56 -0400616 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530617 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400618 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000619 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400620 }
621 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530622}
623
624// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530625func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700626 dh.lockDevice.Lock()
627 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000628 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400629
npujarec5762e2020-01-01 14:08:48 +0530630 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400631 if err != nil || device == nil {
632 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000633 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400634 }
635
636 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400637
638 //Update the device oper state and connection status
639 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400640 dh.device = cloned
641
David K. Bainbridge794735f2020-02-11 21:01:37 -0800642 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000643 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400644 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400645
646 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530647 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400648 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000649 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400650 }
651 for _, onuDevice := range onuDevices.Items {
652
653 // Update onu state as down in onu adapter
654 onuInd := oop.OnuIndication{}
655 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800656 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700657 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800658 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400659 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800660 "source": "openolt",
661 "onu-indicator": onuInd,
662 "device-type": onuDevice.Type,
663 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700664 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700665 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400666 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700667 /* Discovered ONUs entries need to be cleared , since after OLT
668 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530669 dh.discOnus = sync.Map{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000670 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700671 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530672}
673
674// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530675func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400676 var err error
Girish Kumar93e91742020-07-27 16:43:19 +0000677 // Use Intercepters to automatically inject and publish Open Tracing Spans by this GRPC client
678 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
679 grpc.WithInsecure(),
680 grpc.WithBlock(),
681 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
682 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer())),
683 )),
684 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
685 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(opentracing.GlobalTracer())),
686 )))
687
688 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530689 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530690 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000691 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400692 }
693 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530694}
695
696// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530697func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400698 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530699 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400700 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530701}
702
703// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530704func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530705 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000706 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400707
708 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530709 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
710 if err != nil || device == nil {
711 /*TODO: needs to handle error scenarios */
712 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
713 }
714 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000715 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400716
717 cloned := proto.Clone(device).(*voltha.Device)
718 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
719 cloned.OperStatus = voltha.OperStatus_UNKNOWN
720 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530721 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
722 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 -0400723 }
724
Chaitrashree G S44124192019-08-07 20:21:36 -0400725 // 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 +0530726 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400727 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530728 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400729 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400730 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
731 // all the modules initialized and ready to handle incoming ONUs.
732
Thomas Lee S985938d2020-05-04 11:40:41 +0530733 err = dh.initializeDeviceHandlerModules(ctx)
734 if err != nil {
735 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 -0400736 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400737
738 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800739 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530740 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400741 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800742 }
743 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400744 return nil
745 }
746
Neha Sharma8f4e4322020-08-06 10:51:53 +0000747 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400748 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400749 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400750 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400751 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400752 dh.populateActivePorts(ctx, ports)
753 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
754 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400755 }
756
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400757 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530758 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 -0400759 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530760
cuilin20187b2a8c32019-03-26 19:52:28 -0700761 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800762 go func() {
763 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400764 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800765 }
766 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000767 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000768
769 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000770 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000771 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700772 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530773}
774
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400775func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000776 deviceInfo, err := dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400777
778 if err != nil {
779 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
780 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400781 // Instantiate resource manager
Neha Sharma3f221ae2020-04-29 19:02:12 +0000782 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 -0400783 return olterrors.ErrResourceManagerInstantiating
784 }
785
786 // Instantiate flow manager
787 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
788 return olterrors.ErrResourceManagerInstantiating
789
790 }
791 /* TODO: Instantiate Alarm , stats , BW managers */
792 /* Instantiating Event Manager to handle Alarms and KPIs */
793 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
794
795 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000796 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400797
798 return nil
799
800}
801
Neha Sharma96b7bf22020-06-15 10:37:32 +0000802func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400803 var err error
804 var deviceInfo *oop.DeviceInfo
805
Neha Sharma8f4e4322020-08-06 10:51:53 +0000806 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400807
808 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000809 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400810 }
811 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000812 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400813 }
814
Neha Sharma96b7bf22020-06-15 10:37:32 +0000815 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400816 dh.device.Root = true
817 dh.device.Vendor = deviceInfo.Vendor
818 dh.device.Model = deviceInfo.Model
819 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
820 dh.device.HardwareVersion = deviceInfo.HardwareVersion
821 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
822
823 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000824 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400825 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000826 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400827 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000828 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400829 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000830 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400831 dh.device.MacAddress = genmac
832 } else {
833 dh.device.MacAddress = deviceInfo.DeviceId
834 }
835
836 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000837 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000838 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400839 }
840
841 return deviceInfo, nil
842}
843
Neha Sharma96b7bf22020-06-15 10:37:32 +0000844func startCollector(ctx context.Context, dh *DeviceHandler) {
845 logger.Debugf(ctx, "starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530846 for {
847 select {
848 case <-dh.stopCollector:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"deviceID:": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530850 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000851 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700852
Neha Sharma8f4e4322020-08-06 10:51:53 +0000853 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400854 if err != nil {
855 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
856 continue
857 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530858 for _, port := range ports {
859 // NNI Stats
860 if port.Type == voltha.Port_ETHERNET_NNI {
861 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
862 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000863 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
864 go dh.portStats.publishMetrics(ctx, cmnni, port, dh.device.Id, dh.device.Type)
865 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530866 }
867 // PON Stats
868 if port.Type == voltha.Port_PON_OLT {
869 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
870 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
871 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000872 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
873 go dh.portStats.publishMetrics(ctx, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530874 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000875 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500876 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530877 }
878 }
879 }
880}
881
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700882//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530883func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400884 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000885 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530886 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530887
888 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400889 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
890 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530891 }
892
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400893 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530894}
895
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700896//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530897func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700898 return &ic.SwitchCapability{
899 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530900 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700901 HwDesc: "open_pon",
902 SwDesc: "open_pon",
903 SerialNum: dh.device.SerialNumber,
904 },
905 SwitchFeatures: &of.OfpSwitchFeatures{
906 NBuffers: 256,
907 NTables: 2,
908 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
909 of.OfpCapabilities_OFPC_TABLE_STATS |
910 of.OfpCapabilities_OFPC_PORT_STATS |
911 of.OfpCapabilities_OFPC_GROUP_STATS),
912 },
913 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530914}
915
Neha Sharma96b7bf22020-06-15 10:37:32 +0000916func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
917 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 -0700918 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700919 var deviceID string
920 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700921
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400922 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700923 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000924 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 -0700925 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
926 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400927
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700928 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530929
930 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
931
Neha Sharma96b7bf22020-06-15 10:37:32 +0000932 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 -0700933 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700934 kwargs := make(map[string]interface{})
935 kwargs["onu_id"] = omciInd.OnuId
936 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700937
Neha Sharma8f4e4322020-08-06 10:51:53 +0000938 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700939 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530940 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700941 "intf-id": omciInd.IntfId,
942 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700943 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700944 deviceType = onuDevice.Type
945 deviceID = onuDevice.Id
946 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
947 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530948 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700949 } else {
950 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +0000951 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 +0530952 deviceType = onuInCache.(*OnuDevice).deviceType
953 deviceID = onuInCache.(*OnuDevice).deviceID
954 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700955 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700956
957 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +0000958 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
Thomas Lee S985938d2020-05-04 11:40:41 +0530959 ic.InterAdapterMessageType_OMCI_REQUEST, dh.device.Type, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800960 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530961 return olterrors.NewErrCommunication("omci-request", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530962 "source": dh.device.Type,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800963 "destination": deviceType,
964 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000965 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700966 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800967 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530968}
969
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700970//ProcessInterAdapterMessage sends the proxied messages to the target device
971// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
972// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +0000973func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
974 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700975 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700977 fromTopic := msg.Header.FromTopic
978 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700979 toDeviceID := msg.Header.ToDeviceId
980 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700981
Neha Sharma96b7bf22020-06-15 10:37:32 +0000982 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 -0700983
984 msgBody := msg.GetBody()
985
986 omciMsg := &ic.InterAdapterOmciMessage{}
987 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000988 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700989 }
990
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700991 if omciMsg.GetProxyAddress() == nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +0000992 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700993 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530994 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800995 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000996 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700997 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000998 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
999 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301000 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001001 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001002 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001003 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001004 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001005 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1006 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301007 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001008 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001009 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001010 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001011 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001012 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001013 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001014 }
1015 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301016}
1017
Neha Sharma96b7bf22020-06-15 10:37:32 +00001018func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001019 var intfID uint32
1020 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001021 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001022 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001023 intfID = onuDevice.ProxyAddress.GetChannelId()
1024 onuID = onuDevice.ProxyAddress.GetOnuId()
1025 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001026 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001027 intfID = omciMsg.GetProxyAddress().GetChannelId()
1028 onuID = omciMsg.GetProxyAddress().GetOnuId()
1029 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001030 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001031 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001032 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 -08001033
Thomas Lee S94109f12020-03-03 16:39:29 +05301034 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001035 "intf-id": intfID,
1036 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001037 }
1038
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001039 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1040 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001041 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001042 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1043 hex.Encode(hexPkt, omciMsg.Message)
1044 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1045
1046 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1047 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1048 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001049 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001050 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001051
Neha Sharma8f4e4322020-08-06 10:51:53 +00001052 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001053 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301054 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001055 "intf-id": intfID,
1056 "onu-id": onuID,
1057 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001058 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001059 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001060}
1061
David K. Bainbridge794735f2020-02-11 21:01:37 -08001062func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001063 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 +02001064 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001065 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001066 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001067 // TODO: need resource manager
1068 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001069 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301070 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001071 st, _ := status.FromError(err)
1072 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001073 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1074
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001075 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301076 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001077 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001078 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001079 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001080 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001082}
1083
David K. Bainbridge794735f2020-02-11 21:01:37 -08001084func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001085 channelID := onuDiscInd.GetIntfId()
1086 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001087
Neha Sharma96b7bf22020-06-15 10:37:32 +00001088 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301089
cuilin20187b2a8c32019-03-26 19:52:28 -07001090 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001091 if sn != "" {
1092 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001093 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001094 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001095 }
1096
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301097 var alarmInd oop.OnuAlarmIndication
1098 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001099 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301100
1101 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1102 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1103 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1104 OnuLosRaise event sent for it */
1105 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1106 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1107 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001108 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301109 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1110 "currentIntfId": onuDiscInd.GetIntfId()})
1111 // TODO:: Should we need to ignore raising OnuLosClear event
1112 // when onu connected to different PON?
1113 }
1114 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1115 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1116 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001117 go func() {
1118 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1119 logger.Debugw(ctx, "indication-failed", log.Fields{"error": err})
1120 }
1121 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301122 }
1123 return true
1124 })
1125
Neha Sharma96b7bf22020-06-15 10:37:32 +00001126 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001127 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001128 }
1129
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001130 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001131
1132 // check the ONU is already know to the OLT
1133 // NOTE the second time the ONU is discovered this should return a device
1134 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1135
1136 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001137 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 -08001138 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001139 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 -08001140 switch e.Code() {
1141 case codes.Internal:
1142 // this probably means NOT FOUND, so just create a new device
1143 onuDevice = nil
1144 case codes.DeadlineExceeded:
1145 // if the call times out, cleanup and exit
1146 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001147 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001148 }
1149 }
1150 }
1151
1152 if onuDevice == nil {
1153 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001154 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001155 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001156 ponintfid := onuDiscInd.GetIntfId()
1157 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301158 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001159 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001160
Neha Sharma96b7bf22020-06-15 10:37:32 +00001161 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001162
1163 if err != nil {
1164 // if we can't create an ID in resource manager,
1165 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001166 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001167 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001168 "pon-intf-id": ponintfid,
1169 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001170 }
1171
Neha Sharma8f4e4322020-08-06 10:51:53 +00001172 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001173 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001174 dh.discOnus.Delete(sn)
1175 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 +05301176 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001177 "pon-intf-id": ponintfid,
1178 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001179 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04001180 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano()); err != nil {
1181 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"error": err})
1182 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001183 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301184 log.Fields{"onuDevice": onuDevice,
1185 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001186 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301187 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001188 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001189
1190 // we can now use the existing ONU Id
1191 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001192 //Insert the ONU into cache to use in OnuIndication.
1193 //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 +00001194 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001195 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301196 "intfId": onuDiscInd.GetIntfId(),
1197 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001198 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001199
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301200 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301201 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001202 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301203 log.Fields{"onu": onuDev,
1204 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001205
Kent Hagermane6ff1012020-07-14 15:07:53 -04001206 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301207 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001209 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001210 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001212 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301213 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001214 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001215 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001216 }
1217 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001218}
1219
Neha Sharma96b7bf22020-06-15 10:37:32 +00001220func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001221 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1222
1223 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001224 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001225 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001226 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001227 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001228 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301229 log.Fields{"onuId": onuInd.OnuId,
1230 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301231 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001232 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301233
David K. Bainbridge794735f2020-02-11 21:01:37 -08001234 errFields := log.Fields{"device-id": dh.device.Id}
1235
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301236 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1237
Mahir Gunyele77977b2019-06-27 05:36:22 -07001238 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1239 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001240 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001241 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001242 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001243 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1244 if serialNumber != "" {
1245 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001246 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001247 } else {
1248 kwargs["onu_id"] = onuInd.OnuId
1249 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 errFields["onu-id"] = onuInd.OnuId
1251 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001252 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001253 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001254 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001255
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001257 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001258 }
1259
David K. Bainbridge794735f2020-02-11 21:01:37 -08001260 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001261 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262 "previousIntfId": onuDevice.ParentPortNo,
1263 "currentIntfId": ponPort})
1264 }
1265
1266 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001267 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301268 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1269 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301270 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001271 }
1272 if !foundInCache {
1273 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1274
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301275 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 -08001276
1277 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001278 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001279 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001280 }
1281 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001282}
1283
Neha Sharma96b7bf22020-06-15 10:37:32 +00001284func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001285 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 -07001286 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1287 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1288 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1289 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001290 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001291 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1292 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001293 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001294 onuInd.OperState = "down"
1295 }
1296 }
1297
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 switch onuInd.OperState {
1299 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001300 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 -07001301 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301302 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1304 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301305 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 "onu-indicator": onuInd,
1307 "source": "openolt",
1308 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001309 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001310 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001311 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001312 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 -04001313 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301314 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001315 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1316 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301317 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001318 "onu-indicator": onuInd,
1319 "source": "openolt",
1320 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001321 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001322 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001323 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001324 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001325 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001327}
1328
cuilin20187b2a8c32019-03-26 19:52:28 -07001329func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1330 if serialNum != nil {
1331 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001332 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001333 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001334}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001335func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1336 decodedStr, err := hex.DecodeString(serialNum[4:])
1337 if err != nil {
1338 return nil, err
1339 }
1340 return &oop.SerialNumber{
1341 VendorId: []byte(serialNum[:4]),
1342 VendorSpecific: []byte(decodedStr),
1343 }, nil
1344}
cuilin20187b2a8c32019-03-26 19:52:28 -07001345
1346func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1347 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001348 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001349 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1350 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1351 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1352 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1353 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1354 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1355 return tmp
1356}
1357
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001358//UpdateFlowsBulk upates the bulk flow
1359func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301360 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001361}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362
1363//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001364func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1365 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301366 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001367 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301368 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001369 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001371 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001372 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001373 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001374 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001375 "intf-id": parentPort,
1376 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001377 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001378 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 -08001379 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301380}
1381
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001382// SendPacketInToCore sends packet-in to core
1383// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1384// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001385func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001386 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001388 "port": logicalPort,
1389 "packet": hex.EncodeToString(packetPayload),
1390 "device-id": dh.device.Id,
1391 })
1392 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001393 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 +05301394 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001395 "source": "adapter",
1396 "destination": "core",
1397 "device-id": dh.device.Id,
1398 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001399 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001400 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001401 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001402 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001403 "packet": hex.EncodeToString(packetPayload),
1404 "device-id": dh.device.Id,
1405 })
1406 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001407 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001408}
1409
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001410// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001411func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001412 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001413
1414 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1415 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001416 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001417 }
1418
Kent Hagermane6ff1012020-07-14 15:07:53 -04001419 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001420 metrics := dh.metrics.GetSubscriberMetrics()
1421 for _, m := range pmConfigs.Metrics {
1422 metrics[m.Name].Enabled = m.Enabled
1423
1424 }
1425 }
1426}
1427
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001428//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301429func (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 +00001430 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 +01001431
1432 var errorsList []error
1433
Girish Gowdru0c588b22019-04-23 23:24:56 -04001434 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001435 for _, flow := range flows.ToRemove.Items {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001436 dh.incrementActiveFlowRemoveCount(ctx, flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001437
Neha Sharma96b7bf22020-06-15 10:37:32 +00001438 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301439 log.Fields{"device-id": device.Id,
1440 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001441 err := dh.flowMgr.RemoveFlow(ctx, flow)
1442 if err != nil {
1443 errorsList = append(errorsList, err)
1444 }
1445
Neha Sharma96b7bf22020-06-15 10:37:32 +00001446 dh.decrementActiveFlowRemoveCount(ctx, flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001447 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301448
1449 for _, flow := range flows.ToAdd.Items {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001450 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301451 log.Fields{"device-id": device.Id,
1452 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001453 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
Neha Sharma96b7bf22020-06-15 10:37:32 +00001454 dh.waitForFlowRemoveToFinish(ctx, flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001455 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1456 if err != nil {
1457 errorsList = append(errorsList, err)
1458 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301459 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001460 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001461
Girish Gowdracefae192020-03-19 18:14:10 -07001462 // 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 +00001463 if groups != nil {
1464 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001465 err := dh.flowMgr.AddGroup(ctx, group)
1466 if err != nil {
1467 errorsList = append(errorsList, err)
1468 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001469 }
1470 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001471 err := dh.flowMgr.ModifyGroup(ctx, group)
1472 if err != nil {
1473 errorsList = append(errorsList, err)
1474 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001475 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001476 for _, group := range groups.ToRemove.Items {
1477 err := dh.flowMgr.DeleteGroup(ctx, group)
1478 if err != nil {
1479 errorsList = append(errorsList, err)
1480 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001481 }
1482 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001483 if len(errorsList) > 0 {
1484 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1485 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001486 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001487 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301488}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001489
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001490//DisableDevice disables the given device
1491//It marks the following for the given device:
1492//Device-Handler Admin-State : down
1493//Device Port-State: UNKNOWN
1494//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001495func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001496 /* On device disable ,admin state update has to be done prior sending request to agent since
1497 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001498 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001499 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001500 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001501 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001502 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001503 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001504 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001505 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001506 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001507 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301508
1509 dh.discOnus = sync.Map{}
1510 dh.onus = sync.Map{}
1511
Thomas Lee S85f37312020-04-03 17:06:12 +05301512 //stopping the stats collector
1513 dh.stopCollector <- true
1514
Neha Sharma96b7bf22020-06-15 10:37:32 +00001515 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001516 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301517 //Update device Admin state
1518 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001519 // 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 +00001520 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 -04001521 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001522 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001523 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001524 return nil
1525}
1526
Neha Sharma96b7bf22020-06-15 10:37:32 +00001527func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001528 // Update onu state as unreachable in onu adapter
1529 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301530 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001531 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001532 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001533 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001534 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 -04001535 }
1536 if onuDevices != nil {
1537 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001538 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001539 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1540 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001541 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301542 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001543 }
1544
1545 }
1546 }
1547
1548}
1549
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001550//ReenableDevice re-enables the olt device after disable
1551//It marks the following for the given device:
1552//Device-Handler Admin-State : up
1553//Device Port-State: ACTIVE
1554//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001555func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001556 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301557 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001558 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301559 }
1560 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001562
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001563 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001564
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001565 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1566 if err != nil {
1567 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device": device.Id}, err)
1568 }
1569 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001570 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001571 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001572 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001573 device.OperStatus = voltha.OperStatus_ACTIVE
1574 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001575
Neha Sharma8f4e4322020-08-06 10:51:53 +00001576 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 +05301577 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001578 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001579 "connect-status": device.ConnectStatus,
1580 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001581 }
kesavand39e0aa32020-01-28 20:58:50 -05001582
Neha Sharma96b7bf22020-06-15 10:37:32 +00001583 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001584
1585 return nil
1586}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001587
npujarec5762e2020-01-01 14:08:48 +05301588func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001589 var uniID uint32
1590 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301591 for _, port := range onu.UniPorts {
1592 uniID = UniIDFromPortNum(uint32(port))
Neha Sharma96b7bf22020-06-15 10:37:32 +00001593 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001594 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301595 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001596 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001597 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301599 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001600 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301601 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001602 }
npujarec5762e2020-01-01 14:08:48 +05301603 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001604 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301605 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001606 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001607 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001608 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301609 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001610 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001611 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001612 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301613 }
npujarec5762e2020-01-01 14:08:48 +05301614 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1615 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001616 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301617 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001618 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Esin Karaman7fb80c22020-07-16 14:23:33 +00001619 if err = dh.resourceMgr.DelGemPortPktInOfAllServices(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001620 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 +00001621 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001622 }
1623 return nil
1624}
1625
npujarec5762e2020-01-01 14:08:48 +05301626func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001627 nniUniID := -1
1628 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301629
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001630 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301631 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001632 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001633 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301634 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301635 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001636 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001637 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001638 logger.Debugw(ctx, "nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301639 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301640 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +00001641 logger.Debugw(ctx, "current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301642 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301643 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301644 }
npujarec5762e2020-01-01 14:08:48 +05301645 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001646 }
npujarec5762e2020-01-01 14:08:48 +05301647 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001648 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301649 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001650 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001651}
1652
1653// 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 +05301654func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001655 logger.Debug(ctx, "function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001656 /* Clear the KV store data associated with the all the UNI ports
1657 This clears up flow data and also resource map data for various
1658 other pon resources like alloc_id and gemport_id
1659 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001660 go dh.cleanupDeviceResources(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001661 logger.Debug(ctx, "removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001662 // Stop the Stats collector
1663 dh.stopCollector <- true
1664 // stop the heartbeat check routine
1665 dh.stopHeartbeatCheck <- true
1666 //Reset the state
1667 if dh.Client != nil {
1668 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301669 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001670 }
1671 }
1672 cloned := proto.Clone(device).(*voltha.Device)
1673 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1674 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1675 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1676 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1677 "device-id": device.Id,
1678 "connect-status": cloned.ConnectStatus,
1679 "oper-status": cloned.OperStatus}, err).Log()
1680 }
1681 return nil
1682}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001683func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001684
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001685 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301686 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1687 var ponPort uint32
1688 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1689 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301690 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301691 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001692 _ = olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001693 "device-id": dh.device.Id,
Kent Hagermane6ff1012020-07-14 15:07:53 -04001694 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301695 }
1696 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301697 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001698 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301699 if err = dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001700 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301701 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301702 // Clear flowids for gem cache.
1703 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301704 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301705 }
1706 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301707 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301708 }
npujarec5762e2020-01-01 14:08:48 +05301709 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301710 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301711 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301712 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001713 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001714 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001715 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001716 /* Clear the flows from KV store associated with NNI port.
1717 There are mostly trap rules from NNI port (like LLDP)
1718 */
npujarec5762e2020-01-01 14:08:48 +05301719 if err := dh.clearNNIData(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001720 logger.Errorw(ctx, "failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001721 }
A R Karthick1f85b802019-10-11 05:06:05 +00001722
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001723 /* Clear the resource pool for each PON port in the background */
Kent Hagermane6ff1012020-07-14 15:07:53 -04001724 go func() {
1725 if err := dh.resourceMgr.Delete(ctx); err != nil {
1726 logger.Debug(ctx, err)
1727 }
1728 }()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001729 }
A R Karthick1f85b802019-10-11 05:06:05 +00001730
Devmalya Paul495b94a2019-08-27 19:42:00 -04001731 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301732 dh.onus.Range(func(key interface{}, value interface{}) bool {
1733 dh.onus.Delete(key)
1734 return true
1735 })
1736
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001737 /*Delete discovered ONU map for the device*/
1738 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1739 dh.discOnus.Delete(key)
1740 return true
1741 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001742}
1743
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001744//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001745func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001746 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301747 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001748 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001749 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001750 return nil
1751}
1752
David K. Bainbridge794735f2020-02-11 21:01:37 -08001753func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001754 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001755 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001756 "packet-indication": *packetIn,
1757 "device-id": dh.device.Id,
1758 "packet": hex.EncodeToString(packetIn.Pkt),
1759 })
1760 }
npujarec5762e2020-01-01 14:08:48 +05301761 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001762 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001763 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001764 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001765 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001766 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001767 "logical-port-num": logicalPortNum,
1768 "device-id": dh.device.Id,
1769 "packet": hex.EncodeToString(packetIn.Pkt),
1770 })
1771 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001772
Neha Sharma8f4e4322020-08-06 10:51:53 +00001773 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 +05301774 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001775 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301776 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001777 "device-id": dh.device.Id,
1778 "packet": hex.EncodeToString(packetIn.Pkt),
1779 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001780 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001781
Matteo Scandolo92186242020-06-12 10:54:18 -07001782 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001783 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001784 "packet": hex.EncodeToString(packetIn.Pkt),
1785 "device-id": dh.device.Id,
1786 })
1787 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001788 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001789}
1790
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001791// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301792func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001793 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001794 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001795 "device-id": dh.device.Id,
1796 "egress-port-no": egressPortNo,
1797 "pkt-length": len(packet.Data),
1798 "packet": hex.EncodeToString(packet.Data),
1799 })
1800 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001801
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001802 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001803 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001804 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1805 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301806 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1807 // Do not packet-out lldp packets on uni port.
1808 // ONOS has no clue about uni/nni ports, it just packets out on all
1809 // available ports on the Logical Switch. It should not be interested
1810 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001812 "device-id": dh.device.Id,
1813 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301814 return nil
1815 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001816 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1817 if innerEthType == 0x8100 {
1818 // q-in-q 802.1ad or 802.1q double tagged packet.
1819 // slice out the outer tag.
1820 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001821 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001822 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001823 "packet-data": hex.EncodeToString(packet.Data),
1824 "device-id": dh.device.Id,
1825 })
1826 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001827 }
1828 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001829 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1830 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001831 uniID := UniIDFromPortNum(uint32(egressPortNo))
1832
Esin Karaman7fb80c22020-07-16 14:23:33 +00001833 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001834 if err != nil {
1835 // In this case the openolt agent will receive the gemPortID as 0.
1836 // The agent tries to retrieve the gemPortID in this case.
1837 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001839 "intf-id": intfID,
1840 "onu-id": onuID,
1841 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001842 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301843 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001844 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001845 }
1846
1847 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001848
Matteo Scandolo92186242020-06-12 10:54:18 -07001849 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001850 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001851 "egress-port-no": egressPortNo,
1852 "intf-id": intfID,
1853 "onu-id": onuID,
1854 "uni-id": uniID,
1855 "gem-port-id": gemPortID,
1856 "packet": hex.EncodeToString(packet.Data),
1857 "device-id": dh.device.Id,
1858 })
1859 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001860
npujarec5762e2020-01-01 14:08:48 +05301861 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301862 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001863 "source": "adapter",
1864 "destination": "onu",
1865 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001866 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001867 "oni-id": onuID,
1868 "uni-id": uniID,
1869 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001870 "packet": hex.EncodeToString(packet.Data),
1871 "device-id": dh.device.Id,
1872 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001873 }
1874 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001876 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001877 return olterrors.NewErrInvalidValue(log.Fields{
1878 "egress-nni-port": egressPortNo,
1879 "device-id": dh.device.Id,
1880 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001881 }
1882 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001883
Matteo Scandolo92186242020-06-12 10:54:18 -07001884 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001885 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001886 "uplink-pkt": uplinkPkt,
1887 "packet": hex.EncodeToString(packet.Data),
1888 "device-id": dh.device.Id,
1889 })
1890 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001891
npujarec5762e2020-01-01 14:08:48 +05301892 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001893 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1894 "packet": hex.EncodeToString(packet.Data),
1895 "device-id": dh.device.Id,
1896 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001897 }
1898 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001899 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301900 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001901 "egressPortType": egressPortType,
1902 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301903 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001904 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001905 }
1906 return nil
1907}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001908
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001909func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1910 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001911}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301912
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001913func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001914
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301915 // start the heartbeat check towards the OLT.
1916 var timerCheck *time.Timer
1917
1918 for {
1919 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1920 select {
1921 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00001922 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001923 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001924 logger.Warnw(ctx, "hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301925 if timerCheck == nil {
1926 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001927 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301928 }
1929 } else {
1930 if timerCheck != nil {
1931 if timerCheck.Stop() {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001932 logger.Debugw(ctx, "got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301933 }
1934 timerCheck = nil
1935 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001936 logger.Debugw(ctx, "hearbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05301937 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301938 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301939 }
1940 cancel()
1941 case <-dh.stopHeartbeatCheck:
Neha Sharma96b7bf22020-06-15 10:37:32 +00001942 logger.Debugw(ctx, "stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301943 return
1944 }
1945 }
1946}
1947
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001948func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1949 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1950 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001951 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001952 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301953
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001954 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1955 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001956 _ = 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 -04001957 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001958 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001959 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001960 }
1961 go dh.cleanupDeviceResources(ctx)
1962
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001963 dh.lockDevice.RLock()
1964 // Stop the read indication only if it the routine is active
1965 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1966 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1967 // on next execution of the readIndication routine.
1968 if dh.isReadIndicationRoutineActive {
1969 dh.stopIndications <- true
1970 }
1971 dh.lockDevice.RUnlock()
1972
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001973 dh.transitionMap.Handle(ctx, DeviceInit)
1974
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301975 }
1976}
kesavand39e0aa32020-01-28 20:58:50 -05001977
1978// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00001979func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
1980 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
1981 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001982}
1983
1984// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00001985func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
1986 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
1987 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001988}
1989
kdarapu1afeceb2020-02-12 01:38:09 -05001990//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 +00001991func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
1992 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05001993 if port.GetType() == voltha.Port_ETHERNET_NNI {
1994 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001995 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301996 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301997 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001998 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001999 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002000 }
2001 // fetch interfaceid from PortNo
2002 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2003 ponIntf := &oop.Interface{IntfId: ponID}
2004 var operStatus voltha.OperStatus_Types
2005 if enablePort {
2006 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302007 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002008
2009 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302010 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002011 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002012 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002013 }
2014 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002015 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002016 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002017 } else {
2018 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302019 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002020 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302021 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002022 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002023 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002024 }
2025 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002026 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002027 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002028 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302029 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 +05302030 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302031 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002032 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002033 }
2034 return nil
2035}
2036
kdarapu1afeceb2020-02-12 01:38:09 -05002037//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002038func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002039 // Disable the port and update the oper_port_status to core
2040 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002041 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002042 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002043 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302044 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302045 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002046 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002047 }
2048 }
2049 }
2050 return nil
2051}
2052
2053//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002054func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2055 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2056 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002057 if port.Type == voltha.Port_ETHERNET_NNI {
2058 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002059 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002060 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002061 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002062 }
2063 }
2064 if port.Type == voltha.Port_PON_OLT {
2065 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002066 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002067 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002068 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002069 }
2070 }
2071 }
2072}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002073
2074// ChildDeviceLost deletes ONU and clears pon resources related to it.
2075func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002076 logger.Debugw(ctx, "child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002077 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2078 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002079 onuDevice, ok := dh.onus.Load(onuKey)
2080 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302081 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002082 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002083 "device-id": dh.device.Id,
2084 "onu-id": onuID,
2085 "intf-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002086 }
2087 var sn *oop.SerialNumber
2088 var err error
2089 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302090 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002091 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302092 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002093 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2094 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002095
2096 for uniID := 0; uniID < MaxUnisPerOnu; uniID++ {
2097 var flowRemoveData pendingFlowRemoveData
2098 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uint32(uniID)}
2099 dh.lockDevice.RLock()
2100 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2101 dh.lockDevice.RUnlock()
2102 continue
2103 }
2104 dh.lockDevice.RUnlock()
2105
2106 log.Debugw("wait-for-flow-remove-complete-before-processing-child-device-lost",
2107 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2108 // Wait for all flow removes to finish first
2109 <-flowRemoveData.allFlowsRemoved
2110 log.Debugw("flow-removes-complete-for-subscriber",
2111 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2112 }
2113
2114 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Neha Sharma8f4e4322020-08-06 10:51:53 +00002115 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302116 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302117 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002118 "onu-id": onuID}, err).Log()
2119 }
2120 //clear PON resources associated with ONU
2121 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002122 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002123 logger.Warnw(ctx, "failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002124 "device-id": dh.device.Id,
2125 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002126 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002127 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002128 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002129 "device-id": dh.device.Id,
2130 "intf-id": intfID,
2131 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002132 } else {
2133 for i, onu := range onuGemData {
2134 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002135 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002136 if err := dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002137 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302138 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002139 "onu-device": onu,
2140 "error": err})
2141 }
2142 // Clear flowids for gem cache.
2143 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002144 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002145 }
2146 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002147 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002148 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002149 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002150 "intf-id": intfID,
2151 "onu-device": onu,
2152 "onu-gem": onuGemData,
2153 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002154 //Not returning error on cleanup.
2155 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002156 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002157 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002158 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002159 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002160 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002161 }
2162 }
2163 dh.onus.Delete(onuKey)
2164 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2165 return nil
2166}
Girish Gowdracefae192020-03-19 18:14:10 -07002167
2168func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2169 for _, field := range flows.GetOfbFields(flow) {
2170 if field.Type == flows.IN_PORT {
2171 return field.GetPort()
2172 }
2173 }
2174 return InvalidPort
2175}
2176
2177func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2178 for _, action := range flows.GetActions(flow) {
2179 if action.Type == flows.OUTPUT {
2180 if out := action.GetOutput(); out != nil {
2181 return out.GetPort()
2182 }
2183 }
2184 }
2185 return InvalidPort
2186}
2187
Neha Sharma96b7bf22020-06-15 10:37:32 +00002188func (dh *DeviceHandler) incrementActiveFlowRemoveCount(ctx context.Context, flow *of.OfpFlowStats) {
Girish Gowdracefae192020-03-19 18:14:10 -07002189 inPort, outPort := getPorts(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002190 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 -07002191 if inPort != InvalidPort && outPort != InvalidPort {
2192 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2193 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002194 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 -07002195
2196 dh.lockDevice.Lock()
2197 defer dh.lockDevice.Unlock()
2198 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2199 if !ok {
2200 flowRemoveData = pendingFlowRemoveData{
2201 pendingFlowRemoveCount: 0,
2202 allFlowsRemoved: make(chan struct{}),
2203 }
2204 }
2205 flowRemoveData.pendingFlowRemoveCount++
2206 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2207
Neha Sharma96b7bf22020-06-15 10:37:32 +00002208 logger.Debugw(ctx, "current-flow-remove-count–increment",
Matteo Scandolo92186242020-06-12 10:54:18 -07002209 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
Girish Gowdracefae192020-03-19 18:14:10 -07002210 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2211 }
2212}
2213
Neha Sharma96b7bf22020-06-15 10:37:32 +00002214func (dh *DeviceHandler) decrementActiveFlowRemoveCount(ctx context.Context, flow *of.OfpFlowStats) {
Girish Gowdracefae192020-03-19 18:14:10 -07002215 inPort, outPort := getPorts(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002216 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 -07002217 if inPort != InvalidPort && outPort != InvalidPort {
2218 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2219 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002220 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 -07002221
2222 dh.lockDevice.Lock()
2223 defer dh.lockDevice.Unlock()
2224 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002225 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 -07002226 } else {
2227 if val.pendingFlowRemoveCount > 0 {
2228 val.pendingFlowRemoveCount--
2229 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002230 logger.Debugw(ctx, "current-flow-remove-count-after-decrement",
Matteo Scandolo92186242020-06-12 10:54:18 -07002231 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
Girish Gowdracefae192020-03-19 18:14:10 -07002232 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2233 // If all flow removes have finished, then close the channel to signal the receiver
2234 // to go ahead with flow adds.
2235 if val.pendingFlowRemoveCount == 0 {
2236 close(val.allFlowsRemoved)
2237 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2238 return
2239 }
2240 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2241 }
2242 }
2243}
2244
Neha Sharma96b7bf22020-06-15 10:37:32 +00002245func (dh *DeviceHandler) waitForFlowRemoveToFinish(ctx context.Context, flow *of.OfpFlowStats) {
Girish Gowdracefae192020-03-19 18:14:10 -07002246 var flowRemoveData pendingFlowRemoveData
2247 var ok bool
2248 inPort, outPort := getPorts(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002249 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 -07002250 if inPort != InvalidPort && outPort != InvalidPort {
2251 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2252 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002253 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 -07002254
2255 dh.lockDevice.RLock()
2256 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002257 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 -07002258 dh.lockDevice.RUnlock()
2259 return
2260 }
2261 dh.lockDevice.RUnlock()
2262
2263 // Wait for all flow removes to finish first
2264 <-flowRemoveData.allFlowsRemoved
2265
Neha Sharma96b7bf22020-06-15 10:37:32 +00002266 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 -07002267 }
2268}
2269
2270func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2271 inPort := getInPortFromFlow(flow)
2272 outPort := getOutPortFromFlow(flow)
2273
2274 if inPort == InvalidPort || outPort == InvalidPort {
2275 return inPort, outPort
2276 }
2277
2278 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2279 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2280 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2281 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2282 return uniPort, outPort
2283 }
2284 }
2285 } else {
2286 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2287 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2288 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2289 return inPort, uniPort
2290 }
2291 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2292 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2293 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2294 return uniPort, outPort
2295 }
2296 }
2297 }
2298
2299 return InvalidPort, InvalidPort
2300}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002301
2302func extractOmciTransactionID(omciPkt []byte) uint16 {
2303 if len(omciPkt) > 3 {
2304 d := omciPkt[0:2]
2305 transid := binary.BigEndian.Uint16(d)
2306 return transid
2307 }
2308 return 0
2309}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002310
2311// StoreOnuDevice stores the onu parameters to the local cache.
2312func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2313 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2314 dh.onus.Store(onuKey, onuDevice)
2315}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002316
Neha Sharma8f4e4322020-08-06 10:51:53 +00002317func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002318 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002319 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002320 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002321 resp := new(voltha.ReturnValues)
2322 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002323 ctx = log.WithSpanFromContext(context.Background(), ctx)
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002324 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002325 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2326 return nil, err
2327 }
2328 ID = device.ProxyAddress.GetOnuId()
2329 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2330 valueparam.Onu = &Onu
2331 valueparam.Value = value
2332
2333 // This API is unsupported until agent patch is added
2334 resp.Unsupported = uint32(value)
2335 _ = ctx
2336
2337 // Uncomment this code once agent changes are complete and tests
2338 /*
2339 resp, err = dh.Client.GetValue(ctx, valueparam)
2340 if err != nil {
2341 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2342 return nil, err
2343 }
2344 */
2345
2346 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2347 return resp, nil
2348}