blob: 2e04e21682786158f7b1bfc9e6a0ab44168ca744 [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"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080037
Girish Gowdraa09aeab2020-09-14 16:30:52 -070038 "github.com/opencord/voltha-lib-go/v4/pkg/adapters/adapterif"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080039 "github.com/opencord/voltha-lib-go/v4/pkg/config"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070040 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
41 "github.com/opencord/voltha-lib-go/v4/pkg/log"
42 "github.com/opencord/voltha-lib-go/v4/pkg/pmmetrics"
Matteo Scandolodfa7a972020-11-06 13:03:40 -080043
Thomas Lee S94109f12020-03-03 16:39:29 +053044 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080045 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070046 "github.com/opencord/voltha-protos/v4/go/common"
47 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
48 of "github.com/opencord/voltha-protos/v4/go/openflow_13"
49 oop "github.com/opencord/voltha-protos/v4/go/openolt"
50 "github.com/opencord/voltha-protos/v4/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070051 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040052 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040053 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053054)
55
salmansiddiqui7ac62132019-08-22 03:58:50 +000056// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040057const (
Girish Gowdraa09aeab2020-09-14 16:30:52 -070058 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040059)
60
Phaneendra Manda4c62c802019-03-06 21:37:49 +053061//DeviceHandler will interact with the OLT device.
62type DeviceHandler struct {
Matteo Scandolodfa7a972020-11-06 13:03:40 -080063 cm *config.ConfigManager
cuilin20187b2a8c32019-03-26 19:52:28 -070064 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053065 coreProxy adapterif.CoreProxy
66 AdapterProxy adapterif.AdapterProxy
67 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070068 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070069 exitChannel chan int
70 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053071 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070072 transitionMap *TransitionMap
73 clientCon *grpc.ClientConn
Girish Gowdra9602eb42020-09-09 15:50:39 -070074 flowMgr []*OpenOltFlowMgr
75 groupMgr *OpenOltGroupMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040076 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053077 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053078
Girish Gowdra3ab6d212020-03-24 17:33:15 -070079 discOnus sync.Map
80 onus sync.Map
81 portStats *OpenOltStatisticsMgr
82 metrics *pmmetrics.PmMetrics
83 stopCollector chan bool
84 stopHeartbeatCheck chan bool
85 activePorts sync.Map
86 stopIndications chan bool
87 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -070088
Mahir Gunyel2fb81472020-12-16 23:18:34 -080089 totalPonPorts uint32
90 perOnuChannel map[string]onuIndicationChannels
91 perOnuChannelLock sync.Mutex
Mahir Gunyela3f9add2019-06-06 15:13:19 -070092}
93
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070094//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -070095type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070096 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -070097 deviceType string
98 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070099 onuID uint32
100 intfID uint32
101 proxyDeviceID string
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530102 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400103 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700104}
105
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800106type perOnuIndication struct {
107 ctx context.Context
108 indication *oop.Indication
109 serialNumber string
110}
111
112type onuIndicationChannels struct {
113 indicationChannel chan perOnuIndication
114 stopChannel chan struct{}
115}
116
Naga Manjunath7615e552019-10-11 22:35:47 +0530117var pmNames = []string{
118 "rx_bytes",
119 "rx_packets",
120 "rx_mcast_packets",
121 "rx_bcast_packets",
122 "tx_bytes",
123 "tx_packets",
124 "tx_mcast_packets",
125 "tx_bcast_packets",
126}
127
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700128//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530129func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700130 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700131 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700132 device.deviceType = deviceTp
133 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 device.onuID = onuID
135 device.intfID = intfID
136 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530137 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700138 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530139}
140
141//NewDeviceHandler creates a new device handler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800142func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT, cm *config.ConfigManager) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700143 var dh DeviceHandler
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800144 dh.cm = cm
cuilin20187b2a8c32019-03-26 19:52:28 -0700145 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400146 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400147 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700148 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700149 dh.device = cloned
150 dh.openOLT = adapter
151 dh.exitChannel = make(chan int, 1)
152 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530153 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530154 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530155 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 -0500156 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400157 dh.stopIndications = make(chan bool, 1)
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800158 dh.perOnuChannel = make(map[string]onuIndicationChannels)
cuilin20187b2a8c32019-03-26 19:52:28 -0700159 //TODO initialize the support classes.
160 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530161}
162
163// start save the device to the data model
164func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700165 dh.lockDevice.Lock()
166 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000167 logger.Debugw(ctx, "starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700168 // Add the initial device to the local model
Neha Sharma96b7bf22020-06-15 10:37:32 +0000169 logger.Debug(ctx, "device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530170}
171
172// stop stops the device dh. Not much to do for now
173func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700174 dh.lockDevice.Lock()
175 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000176 logger.Debug(ctx, "stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700177 dh.exitChannel <- 1
Neha Sharma96b7bf22020-06-15 10:37:32 +0000178 logger.Debug(ctx, "device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530179}
180
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400181func macifyIP(ip net.IP) string {
182 if len(ip) > 0 {
183 oct1 := strconv.FormatInt(int64(ip[12]), 16)
184 oct2 := strconv.FormatInt(int64(ip[13]), 16)
185 oct3 := strconv.FormatInt(int64(ip[14]), 16)
186 oct4 := strconv.FormatInt(int64(ip[15]), 16)
187 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
188 }
189 return ""
190}
191
Neha Sharma96b7bf22020-06-15 10:37:32 +0000192func generateMacFromHost(ctx context.Context, host string) (string, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400193 var genmac string
194 var addr net.IP
195 var ips []string
196 var err error
197
Neha Sharma96b7bf22020-06-15 10:37:32 +0000198 logger.Debugw(ctx, "generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400199
200 if addr = net.ParseIP(host); addr == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000201 logger.Debugw(ctx, "looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400202
203 if ips, err = net.LookupHost(host); err == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000204 logger.Debugw(ctx, "dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400205 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000206 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400207 }
208 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000209 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530210 log.Fields{"host": ips[0],
211 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400212 return genmac, nil
213 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000214 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400215 }
216
217 genmac = macifyIP(addr)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000218 logger.Debugw(ctx, "using-ip-as-mac",
Shrey Baid807a2a02020-04-09 12:52:45 +0530219 log.Fields{"host": host,
220 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400221 return genmac, nil
222}
223
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530224func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700225 slist := strings.Split(mac, ":")
226 result := make([]uint32, len(slist))
227 var err error
228 var tmp int64
229 for index, val := range slist {
230 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
231 return []uint32{1, 2, 3, 4, 5, 6}
232 }
233 result[index] = uint32(tmp)
234 }
235 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530236}
237
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700238//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 -0800239func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530240
David K. Bainbridge794735f2020-02-11 21:01:37 -0800241 switch portType {
242 case voltha.Port_ETHERNET_NNI:
243 return fmt.Sprintf("nni-%d", portNum), nil
244 case voltha.Port_PON_OLT:
245 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700246 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800247
Girish Kumarf26e4882020-03-05 06:49:10 +0000248 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530249}
250
Neha Sharma96b7bf22020-06-15 10:37:32 +0000251func (dh *DeviceHandler) addPort(ctx context.Context, intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000252 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700253 if state == "up" {
254 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500255 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500256 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700257 } else {
258 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500259 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700260 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700261 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400262 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800263 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000264 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400265 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500266
Neha Sharma8f4e4322020-08-06 10:51:53 +0000267 if port, err := dh.coreProxy.GetDevicePort(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, portNum); err == nil && port.Type == portType {
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000268 logger.Debug(ctx, "port-already-exists-updating-oper-status-of-port")
Neha Sharma8f4e4322020-08-06 10:51:53 +0000269 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 -0400270 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
271 "device-id": dh.device.Id,
272 "port-type": portType,
273 "port-number": portNum,
274 "oper-status": operStatus}, err).Log()
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500275 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400276 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500277 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400278 // Now create Port
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700279 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400280 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700281 PortNo: portNum,
282 Label: label,
283 Type: portType,
284 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700285 OfpPort: &of.OfpPort{
286 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
287 Config: 0,
288 State: uint32(of.OfpPortState_OFPPS_LIVE),
289 Curr: capacity,
290 Advertised: capacity,
291 Peer: capacity,
292 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
293 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
294 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700295 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000296 logger.Debugw(ctx, "sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700297 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000298 if err := dh.coreProxy.PortCreated(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000299 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800300 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000301 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400302 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000303 go dh.updateLocalDevice(ctx)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530304 return nil
305}
306
Kent Hagermane6ff1012020-07-14 15:07:53 -0400307func (dh *DeviceHandler) updateLocalDevice(ctx context.Context) {
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530308 dh.lockDevice.Lock()
309 defer dh.lockDevice.Unlock()
Neha Sharma8f4e4322020-08-06 10:51:53 +0000310 device, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530311 if err != nil || device == nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400312 logger.Errorf(ctx, "device-not-found", log.Fields{"device-id": dh.device.Id}, err)
313 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530314 }
315 dh.device = device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530316}
317
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700318// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530319// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800320func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 defer logger.Debugw(ctx, "indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700322 defer func() {
323 dh.lockDevice.Lock()
324 dh.isReadIndicationRoutineActive = false
325 dh.lockDevice.Unlock()
326 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700327 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700328 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700329 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700330 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400331 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530332 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400333 if err != nil || device == nil {
334 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000335 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400336 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400337
David Bainbridgef5879ca2019-12-13 21:17:54 +0000338 // Create an exponential backoff around re-enabling indications. The
339 // maximum elapsed time for the back off is set to 0 so that we will
340 // continue to retry. The max interval defaults to 1m, but is set
341 // here for code clarity
342 indicationBackoff := backoff.NewExponentialBackOff()
343 indicationBackoff.MaxElapsedTime = 0
344 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700345
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700346 dh.lockDevice.Lock()
347 dh.isReadIndicationRoutineActive = true
348 dh.lockDevice.Unlock()
349
Girish Gowdra3f974912020-03-23 20:35:18 -0700350Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700351 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400352 select {
353 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000354 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700355 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400356 default:
357 indication, err := indications.Recv()
358 if err == io.EOF {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000359 logger.Infow(ctx, "eof-for-indications",
Shrey Baid807a2a02020-04-09 12:52:45 +0530360 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530361 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400362 // Use an exponential back off to prevent getting into a tight loop
363 duration := indicationBackoff.NextBackOff()
364 if duration == backoff.Stop {
365 // If we reach a maximum then warn and reset the backoff
366 // timer and keep attempting.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000367 logger.Warnw(ctx, "maximum-indication-backoff-reached--resetting-backoff-timer",
Shrey Baid807a2a02020-04-09 12:52:45 +0530368 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530369 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400370 indicationBackoff.Reset()
371 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700372
373 // On failure process a backoff timer while watching for stopIndications
374 // events
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700375 backoffTimer := time.NewTimer(indicationBackoff.NextBackOff())
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700376 select {
377 case <-dh.stopIndications:
divyadesai3af43e12020-08-18 07:10:54 +0000378 logger.Debugw(ctx, "stopping-collecting-indications-for-olt", log.Fields{"device-id": dh.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700379 if !backoffTimer.Stop() {
380 <-backoffTimer.C
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700381 }
382 break Loop
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700383 case <-backoffTimer.C:
384 // backoffTimer expired continue
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700385 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700386 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
387 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400388 }
389 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000390 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530391 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000392 logger.Errorw(ctx, "read-indication-error",
Shrey Baid807a2a02020-04-09 12:52:45 +0530393 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530394 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700395 // Close the stream, and re-initialize it
396 if err = indications.CloseSend(); err != nil {
397 // Ok to ignore here, because we landed here due to a problem on the stream
398 // In all probability, the closeSend call may fail
Neha Sharma96b7bf22020-06-15 10:37:32 +0000399 logger.Debugw(ctx, "error-closing-send stream--error-ignored",
Shrey Baid807a2a02020-04-09 12:52:45 +0530400 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530401 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700402 }
403 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
404 return err
405 }
406 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400407 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530408 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400409 // Reset backoff if we have a successful receive
410 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400411 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530412 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000413 logger.Debugw(ctx, "olt-is-admin-down, ignore indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530414 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530415 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400416 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400417 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400418 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700419 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700420 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700421 // Close the send stream
422 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700423
Girish Gowdra3f974912020-03-23 20:35:18 -0700424 return nil
425}
426
427func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
428
429 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
430 if err != nil {
431 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
432 }
433 if indications == nil {
434 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
435 }
436
437 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400438}
439
440// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
441func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
442 switch indication.Data.(type) {
443 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
444 return true
445
446 default:
447 return false
448 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700449}
450
David K. Bainbridge794735f2020-02-11 21:01:37 -0800451func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000452 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000453 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530454 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700455 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530456 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700457 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000458 // Send or clear Alarm
Neha Sharma96b7bf22020-06-15 10:37:32 +0000459 if err := dh.eventMgr.oltUpDownIndication(ctx, oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530460 return olterrors.NewErrAdapter("failed-indication", log.Fields{
divyadesai3af43e12020-08-18 07:10:54 +0000461 "device-id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800462 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000463 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800464 }
465 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700466}
467
David K. Bainbridge794735f2020-02-11 21:01:37 -0800468// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530469func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400470 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700471 switch indication.Data.(type) {
472 case *oop.Indication_OltInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000473 span, ctx := log.CreateChildSpan(ctx, "olt-indication", log.Fields{"device-id": dh.device.Id})
474 defer span.Finish()
475
David K. Bainbridge794735f2020-02-11 21:01:37 -0800476 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400477 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800478 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700479 case *oop.Indication_IntfInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000480 span, ctx := log.CreateChildSpan(ctx, "interface-indication", log.Fields{"device-id": dh.device.Id})
481 defer span.Finish()
482
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700483 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800484 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000485 if err := dh.addPort(ctx, intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400486 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487 }
488 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000489 logger.Infow(ctx, "received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 case *oop.Indication_IntfOperInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000491 span, ctx := log.CreateChildSpan(ctx, "interface-oper-indication", log.Fields{"device-id": dh.device.Id})
492 defer span.Finish()
493
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700494 intfOperInd := indication.GetIntfOperInd()
495 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800496 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000497 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400498 _ = 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 -0800499 }
500 }()
Kent Hagermane6ff1012020-07-14 15:07:53 -0400501 if err := dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId()); err != nil {
502 logger.Warn(ctx, err)
503 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700504 } else if intfOperInd.GetType() == "pon" {
505 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
506 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800507 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000508 if err := dh.addPort(ctx, intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400509 _ = 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 -0800510 }
511 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000512 go dh.eventMgr.oltIntfOperIndication(ctx, indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700513 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000514 logger.Infow(ctx, "received-interface-oper-indication",
Shrey Baid807a2a02020-04-09 12:52:45 +0530515 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530516 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700517 case *oop.Indication_OnuDiscInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000518 span, ctx := log.CreateChildSpan(ctx, "onu-discovery-indication", log.Fields{"device-id": dh.device.Id})
519 defer span.Finish()
520
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700521 onuDiscInd := indication.GetOnuDiscInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000522 logger.Infow(ctx, "received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700523 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800524 //put message to channel and return immediately
525 dh.putOnuIndicationToChannel(ctx, indication, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700526 case *oop.Indication_OnuInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000527 span, ctx := log.CreateChildSpan(ctx, "onu-indication", log.Fields{"device-id": dh.device.Id})
528 defer span.Finish()
529
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700530 onuInd := indication.GetOnuInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000531 logger.Infow(ctx, "received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
Mahir Gunyel2fb81472020-12-16 23:18:34 -0800532 sn := dh.stringifySerialNumber(onuInd.SerialNumber)
533 //put message to channel and return immediately
534 dh.putOnuIndicationToChannel(ctx, indication, sn)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700535 case *oop.Indication_OmciInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000536 span, ctx := log.CreateChildSpan(ctx, "omci-indication", log.Fields{"device-id": dh.device.Id})
537 defer span.Finish()
538
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700539 omciInd := indication.GetOmciInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000540 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 -0800541 go func() {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000542 if err := dh.omciIndication(ctx, omciInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400543 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800544 }
545 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700546 case *oop.Indication_PktInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000547 span, ctx := log.CreateChildSpan(ctx, "packet-indication", log.Fields{"device-id": dh.device.Id})
548 defer span.Finish()
549
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700550 pktInd := indication.GetPktInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000551 logger.Debugw(ctx, "received-packet-indication", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700552 "intf-type": pktInd.IntfId,
553 "intf-id": pktInd.IntfId,
554 "gem-port-id": pktInd.GemportId,
555 "port-no": pktInd.PortNo,
556 "device-id": dh.device.Id,
557 })
558
559 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 logger.Debugw(ctx, "received-packet-indication-packet", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700561 "intf-type": pktInd.IntfId,
562 "intf-id": pktInd.IntfId,
563 "gem-port-id": pktInd.GemportId,
564 "port-no": pktInd.PortNo,
565 "packet": hex.EncodeToString(pktInd.Pkt),
566 "device-id": dh.device.Id,
567 })
568 }
569
David K. Bainbridge794735f2020-02-11 21:01:37 -0800570 go func() {
571 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400572 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800573 }
574 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700575 case *oop.Indication_PortStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000576 span, ctx := log.CreateChildSpan(ctx, "port-statistics-indication", log.Fields{"device-id": dh.device.Id})
577 defer span.Finish()
578
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700579 portStats := indication.GetPortStats()
Girish Gowdra9602eb42020-09-09 15:50:39 -0700580 go dh.portStats.PortStatisticsIndication(ctx, portStats, dh.totalPonPorts)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700581 case *oop.Indication_FlowStats:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000582 span, ctx := log.CreateChildSpan(ctx, "flow-stats-indication", log.Fields{"device-id": dh.device.Id})
583 defer span.Finish()
584
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700585 flowStats := indication.GetFlowStats()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000586 logger.Infow(ctx, "received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700587 case *oop.Indication_AlarmInd:
Neha Sharma8f4e4322020-08-06 10:51:53 +0000588 span, ctx := log.CreateChildSpan(ctx, "alarm-indication", log.Fields{"device-id": dh.device.Id})
589 defer span.Finish()
590
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700591 alarmInd := indication.GetAlarmInd()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000592 logger.Infow(ctx, "received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
593 go dh.eventMgr.ProcessEvents(ctx, alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700594 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530595}
596
597// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530598func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530599 //starting the stat collector
Neha Sharma96b7bf22020-06-15 10:37:32 +0000600 go startCollector(ctx, dh)
Thomas Lee S85f37312020-04-03 17:06:12 +0530601
Girish Gowdru0c588b22019-04-23 23:24:56 -0400602 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530603 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400604 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000605 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400606 }
Gamze Abaka07868a52020-12-17 14:19:28 +0000607
608 //Clear olt communication failure event
609 dh.device.ConnectStatus = voltha.ConnectStatus_REACHABLE
610 dh.device.OperStatus = voltha.OperStatus_ACTIVE
611 raisedTs := time.Now().UnixNano()
612 go dh.eventMgr.oltCommunicationEvent(ctx, dh.device, raisedTs)
613
Girish Gowdru0c588b22019-04-23 23:24:56 -0400614 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530615}
616
617// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530618func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700619 dh.lockDevice.Lock()
620 defer dh.lockDevice.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000621 logger.Debugw(ctx, "do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400622
npujarec5762e2020-01-01 14:08:48 +0530623 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400624 if err != nil || device == nil {
625 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000626 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400627 }
628
629 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400630
631 //Update the device oper state and connection status
632 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400633 dh.device = cloned
634
David K. Bainbridge794735f2020-02-11 21:01:37 -0800635 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000636 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400637 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400638
639 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530640 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400641 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000642 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400643 }
644 for _, onuDevice := range onuDevices.Items {
645
646 // Update onu state as down in onu adapter
647 onuInd := oop.OnuIndication{}
648 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800649 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +0300650 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800651 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400652 _ = olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +0300653 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800654 "onu-indicator": onuInd,
655 "device-type": onuDevice.Type,
656 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700657 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700658 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400659 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700660 /* Discovered ONUs entries need to be cleared , since after OLT
661 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530662 dh.discOnus = sync.Map{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000663 logger.Debugw(ctx, "do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700664 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530665}
666
667// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530668func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400669 var err error
Girish Kumar93e91742020-07-27 16:43:19 +0000670 // Use Intercepters to automatically inject and publish Open Tracing Spans by this GRPC client
671 dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(),
672 grpc.WithInsecure(),
673 grpc.WithBlock(),
674 grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000675 grpc_opentracing.StreamClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000676 )),
677 grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(
Girish Kumar935f7af2020-08-18 11:59:42 +0000678 grpc_opentracing.UnaryClientInterceptor(grpc_opentracing.WithTracer(log.ActiveTracerProxy{})),
Girish Kumar93e91742020-07-27 16:43:19 +0000679 )))
680
681 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530682 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530683 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000684 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400685 }
686 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530687}
688
689// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530690func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400691 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530692 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400693 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530694}
695
696// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530697func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530698 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000699 logger.Debugw(ctx, "olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400700
701 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530702 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
703 if err != nil || device == nil {
704 /*TODO: needs to handle error scenarios */
705 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
706 }
707 if device.AdminState == voltha.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000708 logger.Debugln(ctx, "do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400709
710 cloned := proto.Clone(device).(*voltha.Device)
711 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
712 cloned.OperStatus = voltha.OperStatus_UNKNOWN
713 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530714 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
715 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 -0400716 }
717
Chaitrashree G S44124192019-08-07 20:21:36 -0400718 // 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 +0530719 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400720 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530721 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400722 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400723 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
724 // all the modules initialized and ready to handle incoming ONUs.
725
Thomas Lee S985938d2020-05-04 11:40:41 +0530726 err = dh.initializeDeviceHandlerModules(ctx)
727 if err != nil {
728 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 -0400729 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400730
731 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800732 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530733 if err = dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400734 _ = olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800735 }
736 }()
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700737
738 go startHeartbeatCheck(ctx, dh)
739
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400740 return nil
741 }
742
Neha Sharma8f4e4322020-08-06 10:51:53 +0000743 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400744 if err != nil {
Girish Gowdrud4245152019-05-10 00:47:31 -0400745 /*TODO: needs to handle error scenarios */
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400746 return olterrors.NewErrAdapter("fetch-ports-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400747 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400748 dh.populateActivePorts(ctx, ports)
749 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
750 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"ports": ports}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400751 }
752
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400753 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530754 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 -0400755 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530756
cuilin20187b2a8c32019-03-26 19:52:28 -0700757 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800758 go func() {
759 if err := dh.readIndications(ctx); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -0400760 _ = olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800761 }
762 }()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000763 go dh.updateLocalDevice(ctx)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000764
765 if device.PmConfigs != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000766 dh.UpdatePmConfig(ctx, device.PmConfigs)
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000767 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700768
769 go startHeartbeatCheck(ctx, dh)
770
cuilin20187b2a8c32019-03-26 19:52:28 -0700771 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530772}
773
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400774func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000775 deviceInfo, err := dh.populateDeviceInfo(ctx)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400776
777 if err != nil {
778 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
779 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700780 dh.totalPonPorts = deviceInfo.GetPonPorts()
781
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400782 // Instantiate resource manager
Matteo Scandolodfa7a972020-11-06 13:03:40 -0800783 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, deviceInfo, dh.cm.Backend.PathPrefix); dh.resourceMgr == nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400784 return olterrors.ErrResourceManagerInstantiating
785 }
786
Girish Gowdra9602eb42020-09-09 15:50:39 -0700787 dh.groupMgr = NewGroupManager(ctx, dh, dh.resourceMgr)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400788
Girish Gowdra9602eb42020-09-09 15:50:39 -0700789 dh.flowMgr = make([]*OpenOltFlowMgr, dh.totalPonPorts)
790 for i := range dh.flowMgr {
791 // Instantiate flow manager
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700792 if dh.flowMgr[i] = NewFlowManager(ctx, dh, dh.resourceMgr, dh.groupMgr, uint32(i)); dh.flowMgr[i] == nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700793 return olterrors.ErrResourceManagerInstantiating
794 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400795 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700796
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400797 /* TODO: Instantiate Alarm , stats , BW managers */
798 /* Instantiating Event Manager to handle Alarms and KPIs */
799 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
800
801 // Stats config for new device
Neha Sharma96b7bf22020-06-15 10:37:32 +0000802 dh.portStats = NewOpenOltStatsMgr(ctx, dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400803
804 return nil
805
806}
807
Neha Sharma96b7bf22020-06-15 10:37:32 +0000808func (dh *DeviceHandler) populateDeviceInfo(ctx context.Context) (*oop.DeviceInfo, error) {
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400809 var err error
810 var deviceInfo *oop.DeviceInfo
811
Neha Sharma8f4e4322020-08-06 10:51:53 +0000812 deviceInfo, err = dh.Client.GetDeviceInfo(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty))
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400813
814 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000815 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400816 }
817 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000818 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400819 }
820
Neha Sharma96b7bf22020-06-15 10:37:32 +0000821 logger.Debugw(ctx, "fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400822 dh.device.Root = true
823 dh.device.Vendor = deviceInfo.Vendor
824 dh.device.Model = deviceInfo.Model
825 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
826 dh.device.HardwareVersion = deviceInfo.HardwareVersion
827 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
828
829 if deviceInfo.DeviceId == "" {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000830 logger.Warnw(ctx, "no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400831 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
Neha Sharma96b7bf22020-06-15 10:37:32 +0000832 genmac, err := generateMacFromHost(ctx, host)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400833 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000834 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400835 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000836 logger.Debugw(ctx, "using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400837 dh.device.MacAddress = genmac
838 } else {
839 dh.device.MacAddress = deviceInfo.DeviceId
840 }
841
842 // Synchronous call to update device - this method is run in its own go routine
Neha Sharma8f4e4322020-08-06 10:51:53 +0000843 if err := dh.coreProxy.DeviceUpdate(log.WithSpanFromContext(context.TODO(), ctx), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000844 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400845 }
846
847 return deviceInfo, nil
848}
849
Neha Sharma96b7bf22020-06-15 10:37:32 +0000850func startCollector(ctx context.Context, dh *DeviceHandler) {
851 logger.Debugf(ctx, "starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530852 for {
853 select {
854 case <-dh.stopCollector:
divyadesai3af43e12020-08-18 07:10:54 +0000855 logger.Debugw(ctx, "stopping-collector-for-olt", log.Fields{"device-id": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530856 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000857 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700858
Neha Sharma8f4e4322020-08-06 10:51:53 +0000859 ports, err := dh.coreProxy.ListDevicePorts(log.WithSpanFromContext(context.Background(), ctx), dh.device.Id)
Kent Hagermanf1db18b2020-07-08 13:38:15 -0400860 if err != nil {
861 logger.Warnw(ctx, "failed-to-list-ports", log.Fields{"device-id": dh.device.Id, "error": err})
862 continue
863 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530864 for _, port := range ports {
865 // NNI Stats
866 if port.Type == voltha.Port_ETHERNET_NNI {
867 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
868 cmnni := dh.portStats.collectNNIMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000869 logger.Debugw(ctx, "collect-nni-metrics", log.Fields{"metrics": cmnni})
870 go dh.portStats.publishMetrics(ctx, cmnni, port, dh.device.Id, dh.device.Type)
871 logger.Debugw(ctx, "publish-nni-metrics", log.Fields{"nni-port": port.Label})
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530872 }
873 // PON Stats
874 if port.Type == voltha.Port_PON_OLT {
875 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
876 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
877 cmpon := dh.portStats.collectPONMetrics(intfID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000878 logger.Debugw(ctx, "collect-pon-metrics", log.Fields{"metrics": cmpon})
879 go dh.portStats.publishMetrics(ctx, cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530880 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000881 logger.Debugw(ctx, "publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500882 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530883 }
884 }
885 }
886}
887
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700888//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530889func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400890 dh.transitionMap = NewTransitionMap(dh)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000891 logger.Infow(ctx, "adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530892 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530893
894 // Now, set the initial PM configuration for that device
Kent Hagermane6ff1012020-07-14 15:07:53 -0400895 if err := dh.coreProxy.DevicePMConfigUpdate(ctx, dh.metrics.ToPmConfigs()); err != nil {
896 _ = olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530897 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530898}
899
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700900//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530901func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700902 return &ic.SwitchCapability{
903 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530904 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700905 HwDesc: "open_pon",
906 SwDesc: "open_pon",
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700907 SerialNum: device.SerialNumber,
cuilin20187b2a8c32019-03-26 19:52:28 -0700908 },
909 SwitchFeatures: &of.OfpSwitchFeatures{
910 NBuffers: 256,
911 NTables: 2,
912 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
913 of.OfpCapabilities_OFPC_TABLE_STATS |
914 of.OfpCapabilities_OFPC_PORT_STATS |
915 of.OfpCapabilities_OFPC_GROUP_STATS),
916 },
917 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530918}
919
Neha Sharma96b7bf22020-06-15 10:37:32 +0000920func (dh *DeviceHandler) omciIndication(ctx context.Context, omciInd *oop.OmciIndication) error {
921 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 -0700922 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700923 var deviceID string
924 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700925
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400926 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700927 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000928 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 -0700929 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
930 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400931
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700932 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530933
934 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
935
Neha Sharma96b7bf22020-06-15 10:37:32 +0000936 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 -0700937 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700938 kwargs := make(map[string]interface{})
939 kwargs["onu_id"] = omciInd.OnuId
940 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700941
Neha Sharma8f4e4322020-08-06 10:51:53 +0000942 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700943 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530944 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700945 "intf-id": omciInd.IntfId,
946 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700947 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700948 deviceType = onuDevice.Type
949 deviceID = onuDevice.Id
950 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
951 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530952 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700953 } else {
954 //found in cache
Neha Sharma96b7bf22020-06-15 10:37:32 +0000955 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 +0530956 deviceType = onuInCache.(*OnuDevice).deviceType
957 deviceID = onuInCache.(*OnuDevice).deviceID
958 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700959 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700960
961 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
Neha Sharma8f4e4322020-08-06 10:51:53 +0000962 if err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx), omciMsg,
serkant.uluderya4aff1862020-09-17 23:35:26 +0300963 ic.InterAdapterMessageType_OMCI_REQUEST, dh.openOLT.config.Topic, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800964 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530965 return olterrors.NewErrCommunication("omci-request", log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +0300966 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800967 "destination": deviceType,
968 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000969 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700970 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800971 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530972}
973
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700974//ProcessInterAdapterMessage sends the proxied messages to the target device
975// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
976// is meant, and then send the unmarshalled omci message to this onu
Neha Sharma96b7bf22020-06-15 10:37:32 +0000977func (dh *DeviceHandler) ProcessInterAdapterMessage(ctx context.Context, msg *ic.InterAdapterMessage) error {
978 logger.Debugw(ctx, "process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700979 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700980 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700981 fromTopic := msg.Header.FromTopic
982 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700983 toDeviceID := msg.Header.ToDeviceId
984 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700985
Neha Sharma96b7bf22020-06-15 10:37:32 +0000986 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 -0700987
988 msgBody := msg.GetBody()
989
990 omciMsg := &ic.InterAdapterOmciMessage{}
991 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000992 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700993 }
994
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700995 if omciMsg.GetProxyAddress() == nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +0000996 onuDevice, err := dh.coreProxy.GetDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, toDeviceID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700997 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530998 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800999 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001000 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001001 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001002 logger.Debugw(ctx, "device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1003 if err := dh.sendProxiedMessage(ctx, onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301004 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001005 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001006 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001007 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001008 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001009 logger.Debugw(ctx, "proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
1010 if err := dh.sendProxiedMessage(ctx, nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301011 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001012 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001013 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001014 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001015 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001016 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001017 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001018 }
1019 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301020}
1021
Neha Sharma96b7bf22020-06-15 10:37:32 +00001022func (dh *DeviceHandler) sendProxiedMessage(ctx context.Context, onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001023 var intfID uint32
1024 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +00001025 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001026 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001027 intfID = onuDevice.ProxyAddress.GetChannelId()
1028 onuID = onuDevice.ProxyAddress.GetOnuId()
1029 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001030 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001031 intfID = omciMsg.GetProxyAddress().GetChannelId()
1032 onuID = omciMsg.GetProxyAddress().GetOnuId()
1033 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001034 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001035 if connectStatus != voltha.ConnectStatus_REACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001036 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 -08001037
Thomas Lee S94109f12020-03-03 16:39:29 +05301038 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001039 "intf-id": intfID,
1040 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001041 }
1042
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001043 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1044 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001045 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001046 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1047 hex.Encode(hexPkt, omciMsg.Message)
1048 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1049
1050 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1051 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1052 transid := extractOmciTransactionID(omciMsg.Message)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001053 logger.Debugw(ctx, "sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001054 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001055
Neha Sharma8f4e4322020-08-06 10:51:53 +00001056 _, err := dh.Client.OmciMsgOut(log.WithSpanFromContext(context.Background(), ctx), omciMessage)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001057 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301058 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001059 "intf-id": intfID,
1060 "onu-id": onuID,
1061 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001062 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001063 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001064}
1065
David K. Bainbridge794735f2020-02-11 21:01:37 -08001066func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
kesavand494c2082020-08-31 11:16:12 +05301067 logger.Debugw(ctx, "activate-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id, "OmccEncryption": dh.openOLT.config.OmccEncryption})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001068 if err := dh.flowMgr[intfID].UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001069 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001070 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001071 // TODO: need resource manager
1072 var pir uint32 = 1000000
kesavand494c2082020-08-31 11:16:12 +05301073 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir, OmccEncryption: dh.openOLT.config.OmccEncryption}
npujarec5762e2020-01-01 14:08:48 +05301074 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001075 st, _ := status.FromError(err)
1076 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001077 logger.Debugw(ctx, "onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
1078
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001079 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301080 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001081 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001082 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001083 logger.Infow(ctx, "activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001084 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001085 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001086}
1087
David K. Bainbridge794735f2020-02-11 21:01:37 -08001088func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001089 channelID := onuDiscInd.GetIntfId()
1090 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001091
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Infow(ctx, "new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301093
cuilin20187b2a8c32019-03-26 19:52:28 -07001094 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001095 if sn != "" {
1096 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001097 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001098 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001099 }
1100
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301101 var alarmInd oop.OnuAlarmIndication
1102 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001103 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301104
1105 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1106 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1107 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1108 OnuLosRaise event sent for it */
1109 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1110 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1111 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001112 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301113 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1114 "currentIntfId": onuDiscInd.GetIntfId()})
1115 // TODO:: Should we need to ignore raising OnuLosClear event
1116 // when onu connected to different PON?
1117 }
1118 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1119 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1120 alarmInd.LosStatus = statusCheckOff
Kent Hagermane6ff1012020-07-14 15:07:53 -04001121 go func() {
1122 if err := dh.eventMgr.onuAlarmIndication(ctx, &alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs); err != nil {
1123 logger.Debugw(ctx, "indication-failed", log.Fields{"error": err})
1124 }
1125 }()
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301126 }
1127 return true
1128 })
1129
Neha Sharma96b7bf22020-06-15 10:37:32 +00001130 logger.Warnw(ctx, "onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001131 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001132 }
1133
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001134 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001135
1136 // check the ONU is already know to the OLT
1137 // NOTE the second time the ONU is discovered this should return a device
1138 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1139
1140 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001141 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 -08001142 if e, ok := status.FromError(err); ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001143 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 -08001144 switch e.Code() {
1145 case codes.Internal:
1146 // this probably means NOT FOUND, so just create a new device
1147 onuDevice = nil
1148 case codes.DeadlineExceeded:
1149 // if the call times out, cleanup and exit
1150 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001151 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001152 }
1153 }
1154 }
1155
1156 if onuDevice == nil {
1157 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Neha Sharma96b7bf22020-06-15 10:37:32 +00001158 logger.Debugw(ctx, "creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001159 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001160 ponintfid := onuDiscInd.GetIntfId()
npujarec5762e2020-01-01 14:08:48 +05301161 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001162
Neha Sharma96b7bf22020-06-15 10:37:32 +00001163 logger.Infow(ctx, "creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001164
1165 if err != nil {
1166 // if we can't create an ID in resource manager,
1167 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001168 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001169 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001170 "pon-intf-id": ponintfid,
1171 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001172 }
1173
Neha Sharma8f4e4322020-08-06 10:51:53 +00001174 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, int(parentPortNo),
Matteo Scandolo945e4012019-12-12 14:16:11 -08001175 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001176 dh.discOnus.Delete(sn)
1177 dh.resourceMgr.FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301178 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001179 "pon-intf-id": ponintfid,
1180 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001181 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04001182 if err := dh.eventMgr.OnuDiscoveryIndication(ctx, onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano()); err != nil {
1183 logger.Warnw(ctx, "discovery-indication-failed", log.Fields{"error": err})
1184 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001185 logger.Infow(ctx, "onu-child-device-added",
Shrey Baid807a2a02020-04-09 12:52:45 +05301186 log.Fields{"onuDevice": onuDevice,
1187 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001188 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301189 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001190 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001191
1192 // we can now use the existing ONU Id
1193 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001194 //Insert the ONU into cache to use in OnuIndication.
1195 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001196 logger.Debugw(ctx, "onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001197 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301198 "intfId": onuDiscInd.GetIntfId(),
1199 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001200 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001201
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301202 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301203 dh.onus.Store(onuKey, onuDev)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001204 logger.Debugw(ctx, "new-onu-device-discovered",
Shrey Baid807a2a02020-04-09 12:52:45 +05301205 log.Fields{"onu": onuDev,
1206 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001207
Kent Hagermane6ff1012020-07-14 15:07:53 -04001208 if err := dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301209 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001211 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001212 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001213 logger.Infow(ctx, "onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
Kent Hagermane6ff1012020-07-14 15:07:53 -04001214 if err := dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301215 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001216 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001217 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 }
1219 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001220}
1221
Mahir Gunyel2fb81472020-12-16 23:18:34 -08001222func (dh *DeviceHandler) onuIndication(ctx context.Context, onuInd *oop.OnuIndication, serialNumber string) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001223
1224 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001225 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001226 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001227 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001228 foundInCache := false
Neha Sharma96b7bf22020-06-15 10:37:32 +00001229 logger.Debugw(ctx, "onu-indication-key-create",
Shrey Baid807a2a02020-04-09 12:52:45 +05301230 log.Fields{"onuId": onuInd.OnuId,
1231 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301232 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001233 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301234
David K. Bainbridge794735f2020-02-11 21:01:37 -08001235 errFields := log.Fields{"device-id": dh.device.Id}
1236
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301237 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1238
Mahir Gunyele77977b2019-06-27 05:36:22 -07001239 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1240 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001241 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
Kent Hagermane6ff1012020-07-14 15:07:53 -04001242 onuDevice, err = dh.coreProxy.GetDevice(ctx, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001243 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001244 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1245 if serialNumber != "" {
1246 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001247 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001248 } else {
1249 kwargs["onu_id"] = onuInd.OnuId
1250 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 errFields["onu-id"] = onuInd.OnuId
1252 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001253 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001254 onuDevice, err = dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001255 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001256
David K. Bainbridge794735f2020-02-11 21:01:37 -08001257 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001258 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001259 }
1260
David K. Bainbridge794735f2020-02-11 21:01:37 -08001261 if onuDevice.ParentPortNo != ponPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001262 logger.Warnw(ctx, "onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 "previousIntfId": onuDevice.ParentPortNo,
1264 "currentIntfId": ponPort})
1265 }
1266
1267 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001268 logger.Warnw(ctx, "onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301269 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1270 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301271 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 }
1273 if !foundInCache {
1274 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1275
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301276 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 -08001277
1278 }
kesavand7cf3a052020-08-28 12:49:18 +05301279 if onuInd.OperState == "down" && onuInd.FailReason != oop.OnuIndication_ONU_ACTIVATION_FAIL_REASON_NONE {
1280 if err := dh.eventMgr.onuActivationIndication(ctx, onuActivationFailEvent, onuInd, dh.device.Id, time.Now().UnixNano()); err != nil {
1281 logger.Warnw(ctx, "onu-activation-indication-reporting-failed", log.Fields{"error": err})
1282 }
1283 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001284 if err := dh.updateOnuStates(ctx, onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001285 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001286 }
1287 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001288}
1289
Neha Sharma96b7bf22020-06-15 10:37:32 +00001290func (dh *DeviceHandler) updateOnuStates(ctx context.Context, onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001291 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 -07001292 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1293 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1294 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1295 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001296 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001297 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1298 if onuInd.OperState != "down" {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001299 logger.Warnw(ctx, "onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001300 onuInd.OperState = "down"
1301 }
1302 }
1303
David K. Bainbridge794735f2020-02-11 21:01:37 -08001304 switch onuInd.OperState {
1305 case "down":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001306 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 -07001307 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301308 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001309 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001310 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301311 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001312 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001313 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001314 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001315 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001316 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001317 case "up":
Neha Sharma96b7bf22020-06-15 10:37:32 +00001318 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 -04001319 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301320 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001321 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001322 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301323 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001324 "onu-indicator": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001325 "source": dh.openOLT.config.Topic,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001327 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001328 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001329 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001330 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001331 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001332 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001333}
1334
cuilin20187b2a8c32019-03-26 19:52:28 -07001335func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1336 if serialNum != nil {
1337 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001338 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001339 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001340}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001341func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1342 decodedStr, err := hex.DecodeString(serialNum[4:])
1343 if err != nil {
1344 return nil, err
1345 }
1346 return &oop.SerialNumber{
1347 VendorId: []byte(serialNum[:4]),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001348 VendorSpecific: decodedStr,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001349 }, nil
1350}
cuilin20187b2a8c32019-03-26 19:52:28 -07001351
1352func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1353 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001355 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1356 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1357 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1358 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1359 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1360 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1361 return tmp
1362}
1363
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001364//UpdateFlowsBulk upates the bulk flow
1365func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301366 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001367}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001368
1369//GetChildDevice returns the child device for given parent port and onu id
Neha Sharma96b7bf22020-06-15 10:37:32 +00001370func (dh *DeviceHandler) GetChildDevice(ctx context.Context, parentPort, onuID uint32) (*voltha.Device, error) {
1371 logger.Debugw(ctx, "getchilddevice",
Shrey Baid807a2a02020-04-09 12:52:45 +05301372 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001373 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301374 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001375 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001376 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001377 kwargs["parent_port_no"] = parentPort
Neha Sharma8f4e4322020-08-06 10:51:53 +00001378 onuDevice, err := dh.coreProxy.GetChildDevice(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001379 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001380 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001381 "intf-id": parentPort,
1382 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001383 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001384 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 -08001385 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301386}
1387
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001388// SendPacketInToCore sends packet-in to core
1389// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1390// The adapter handling the device creates a device specific topic
Neha Sharma96b7bf22020-06-15 10:37:32 +00001391func (dh *DeviceHandler) SendPacketInToCore(ctx context.Context, logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001392 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001393 logger.Debugw(ctx, "send-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001394 "port": logicalPort,
1395 "packet": hex.EncodeToString(packetPayload),
1396 "device-id": dh.device.Id,
1397 })
1398 }
Neha Sharma8f4e4322020-08-06 10:51:53 +00001399 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 +05301400 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001401 "source": "adapter",
1402 "destination": "core",
1403 "device-id": dh.device.Id,
1404 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001405 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001406 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001407 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001408 logger.Debugw(ctx, "sent-packet-in-to-core-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001409 "packet": hex.EncodeToString(packetPayload),
1410 "device-id": dh.device.Id,
1411 })
1412 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001413 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001414}
1415
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001416// UpdatePmConfig updates the pm metrics.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001417func (dh *DeviceHandler) UpdatePmConfig(ctx context.Context, pmConfigs *voltha.PmConfigs) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001418 logger.Infow(ctx, "update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001419
1420 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1421 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001422 logger.Debugf(ctx, "frequency-updated")
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001423 }
1424
Kent Hagermane6ff1012020-07-14 15:07:53 -04001425 if !pmConfigs.Grouped {
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001426 metrics := dh.metrics.GetSubscriberMetrics()
1427 for _, m := range pmConfigs.Metrics {
1428 metrics[m.Name].Enabled = m.Enabled
1429
1430 }
1431 }
1432}
1433
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001434//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301435func (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 +00001436 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 +01001437
1438 var errorsList []error
1439
Girish Gowdru0c588b22019-04-23 23:24:56 -04001440 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001441 for _, flow := range flows.ToRemove.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001442 ponIf := dh.getPonIfFromFlow(flow)
Girish Gowdracefae192020-03-19 18:14:10 -07001443
Neha Sharma96b7bf22020-06-15 10:37:32 +00001444 logger.Debugw(ctx, "removing-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301445 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001446 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301447 "flowToRemove": flow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001448 err := dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, false, nil)
Girish Gowdracefae192020-03-19 18:14:10 -07001449 if err != nil {
1450 errorsList = append(errorsList, err)
1451 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001452 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301453
1454 for _, flow := range flows.ToAdd.Items {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001455 ponIf := dh.getPonIfFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001456 logger.Debugw(ctx, "adding-flow",
Shrey Baid807a2a02020-04-09 12:52:45 +05301457 log.Fields{"device-id": device.Id,
Girish Gowdra9602eb42020-09-09 15:50:39 -07001458 "ponIf": ponIf,
Shrey Baid807a2a02020-04-09 12:52:45 +05301459 "flowToAdd": flow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07001460 err := dh.flowMgr[ponIf].RouteFlowToOnuChannel(ctx, flow, true, flowMetadata)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001461 if err != nil {
1462 errorsList = append(errorsList, err)
1463 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301464 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001465 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001466
Girish Gowdracefae192020-03-19 18:14:10 -07001467 // 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 +00001468 if groups != nil {
1469 for _, group := range groups.ToAdd.Items {
Girish Gowdra9602eb42020-09-09 15:50:39 -07001470 err := dh.groupMgr.AddGroup(ctx, group)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001471 if err != nil {
1472 errorsList = append(errorsList, err)
1473 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001474 }
1475 for _, group := range groups.ToUpdate.Items {
Girish Gowdra9602eb42020-09-09 15:50:39 -07001476 err := dh.groupMgr.ModifyGroup(ctx, group)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001477 if err != nil {
1478 errorsList = append(errorsList, err)
1479 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001480 }
Esin Karamand519bbf2020-07-01 11:16:03 +00001481 for _, group := range groups.ToRemove.Items {
Girish Gowdra9602eb42020-09-09 15:50:39 -07001482 err := dh.groupMgr.DeleteGroup(ctx, group)
Esin Karamand519bbf2020-07-01 11:16:03 +00001483 if err != nil {
1484 errorsList = append(errorsList, err)
1485 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001486 }
1487 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001488 if len(errorsList) > 0 {
1489 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1490 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001491 logger.Debugw(ctx, "updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001492 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301493}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001494
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001495//DisableDevice disables the given device
1496//It marks the following for the given device:
1497//Device-Handler Admin-State : down
1498//Device Port-State: UNKNOWN
1499//Device Oper-State: UNKNOWN
Neha Sharma96b7bf22020-06-15 10:37:32 +00001500func (dh *DeviceHandler) DisableDevice(ctx context.Context, device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001501 /* On device disable ,admin state update has to be done prior sending request to agent since
1502 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001503 if dh.Client != nil {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001504 if _, err := dh.Client.DisableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001505 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001506 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001507 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001508 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001509 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001510 logger.Debugw(ctx, "olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001511 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001512 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301513
1514 dh.discOnus = sync.Map{}
1515 dh.onus = sync.Map{}
1516
Thomas Lee S85f37312020-04-03 17:06:12 +05301517 //stopping the stats collector
1518 dh.stopCollector <- true
1519
Neha Sharma96b7bf22020-06-15 10:37:32 +00001520 go dh.notifyChildDevices(ctx, "unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001521 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301522 //Update device Admin state
1523 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001524 // 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 +00001525 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 -04001526 return olterrors.NewErrAdapter("ports-state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001527 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001528 logger.Debugw(ctx, "disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001529 return nil
1530}
1531
Neha Sharma96b7bf22020-06-15 10:37:32 +00001532func (dh *DeviceHandler) notifyChildDevices(ctx context.Context, state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001533 // Update onu state as unreachable in onu adapter
1534 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301535 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001536 //get the child device for the parent device
Neha Sharma8f4e4322020-08-06 10:51:53 +00001537 onuDevices, err := dh.coreProxy.GetChildDevices(log.WithSpanFromContext(context.TODO(), ctx), dh.device.Id)
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001538 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001539 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 -04001540 }
1541 if onuDevices != nil {
1542 for _, onuDevice := range onuDevices.Items {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001543 err := dh.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.TODO(), ctx), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001544 dh.openOLT.config.Topic, onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001545 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001546 logger.Errorw(ctx, "failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001547 "From Adapter": dh.openOLT.config.Topic, "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001548 }
1549
1550 }
1551 }
1552
1553}
1554
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001555//ReenableDevice re-enables the olt device after disable
1556//It marks the following for the given device:
1557//Device-Handler Admin-State : up
1558//Device Port-State: ACTIVE
1559//Device Oper-State: ACTIVE
Neha Sharma96b7bf22020-06-15 10:37:32 +00001560func (dh *DeviceHandler) ReenableDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001561 if _, err := dh.Client.ReenableOlt(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301562 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001563 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301564 }
1565 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001566 logger.Debug(ctx, "olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001567
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001568 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001569
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001570 ports, err := dh.coreProxy.ListDevicePorts(ctx, device.Id)
1571 if err != nil {
divyadesai3af43e12020-08-18 07:10:54 +00001572 return olterrors.NewErrAdapter("list-ports-failed", log.Fields{"device-id": device.Id}, err)
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001573 }
1574 if err := dh.disableAdminDownPorts(ctx, ports); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001575 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001576 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001577 //Update the device oper status as ACTIVE
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001578 device.OperStatus = voltha.OperStatus_ACTIVE
1579 dh.device = device
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001580
Neha Sharma8f4e4322020-08-06 10:51:53 +00001581 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 +05301582 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001583 "device-id": device.Id,
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001584 "connect-status": device.ConnectStatus,
1585 "oper-status": device.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001586 }
kesavand39e0aa32020-01-28 20:58:50 -05001587
Neha Sharma96b7bf22020-06-15 10:37:32 +00001588 logger.Debugw(ctx, "reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001589
1590 return nil
1591}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001592
npujarec5762e2020-01-01 14:08:48 +05301593func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001594 var uniID uint32
1595 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301596 for _, port := range onu.UniPorts {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001597 uniID = UniIDFromPortNum(port)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001598 logger.Debugw(ctx, "clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001599 /* Delete tech-profile instance from the KV store */
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001600 if err = dh.flowMgr[onu.IntfID].DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001601 logger.Debugw(ctx, "failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001602 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001603 logger.Debugw(ctx, "deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301604 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001605 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301606 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001607 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001608 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001609 logger.Debugw(ctx, "removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301610 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001611 logger.Debugw(ctx, "failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001612 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001613 logger.Debugw(ctx, "removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301614 }
npujarec5762e2020-01-01 14:08:48 +05301615 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1616 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001617 logger.Debugw(ctx, "failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301618 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001619 logger.Debugw(ctx, "removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001620 if err = dh.resourceMgr.DeletePacketInGemPortForOnu(ctx, onu.IntfID, onu.OnuID, port); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001621 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 +00001622 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001623 if err = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID)); err != nil {
1624 logger.Debugw(ctx, "failed-to-remove-flow-for", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
1625 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001626 }
1627 return nil
1628}
1629
npujarec5762e2020-01-01 14:08:48 +05301630func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001631 nniUniID := -1
1632 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301633
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001634 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301635 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001636 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001637 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301638 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301639 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001640 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001641 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001642 logger.Debugw(ctx, "nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301643 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301644 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001645 _ = dh.resourceMgr.RemoveAllFlowsForIntfOnuUniKey(ctx, nniIntfID, -1, -1)
1646
Devmalya Paul495b94a2019-08-27 19:42:00 -04001647 }
npujarec5762e2020-01-01 14:08:48 +05301648 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001649 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301650 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001651
David K. Bainbridge794735f2020-02-11 21:01:37 -08001652 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001653}
1654
1655// 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 +05301656func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001657 logger.Debug(ctx, "function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001658 /* Clear the KV store data associated with the all the UNI ports
1659 This clears up flow data and also resource map data for various
1660 other pon resources like alloc_id and gemport_id
1661 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001662 go dh.cleanupDeviceResources(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001663 logger.Debug(ctx, "removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001664 // Stop the Stats collector
1665 dh.stopCollector <- true
1666 // stop the heartbeat check routine
1667 dh.stopHeartbeatCheck <- true
Himani Chawla49a5d562020-11-25 11:53:44 +05301668 dh.lockDevice.RLock()
1669 // Stop the read indication only if it the routine is active
1670 if dh.isReadIndicationRoutineActive {
1671 dh.stopIndications <- true
1672 }
1673 dh.lockDevice.RUnlock()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001674 //Reset the state
1675 if dh.Client != nil {
1676 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301677 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001678 }
1679 }
Girish Gowdrab1caa442020-10-19 12:24:39 -07001680 // There is no need to update the core about operation status and connection status of the OLT.
1681 // The OLT is getting deleted anyway and the core might have already cleared the OLT device from its DB.
1682 // So any attempt to update the operation status and connection status of the OLT will result in core throwing an error back,
1683 // because the device does not exist in DB.
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001684 return nil
1685}
Kent Hagermane6ff1012020-07-14 15:07:53 -04001686func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001687
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001688 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301689 var ponPort uint32
Girish Gowdra9602eb42020-09-09 15:50:39 -07001690 for ponPort = 0; ponPort < dh.totalPonPorts; ponPort++ {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301691 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301692 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301693 if err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001694 _ = olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001695 "device-id": dh.device.Id,
Kent Hagermane6ff1012020-07-14 15:07:53 -04001696 "pon-port": ponPort}, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301697 }
1698 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301699 onuID := make([]uint32, 1)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001700 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301701 if err = dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001702 logger.Errorw(ctx, "failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301703 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301704 // Clear flowids for gem cache.
1705 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301706 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301707 }
1708 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301709 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301710 }
npujarec5762e2020-01-01 14:08:48 +05301711 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301712 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301713 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301714 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001715 logger.Errorw(ctx, "failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001716 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001717 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001718 /* Clear the flows from KV store associated with NNI port.
1719 There are mostly trap rules from NNI port (like LLDP)
1720 */
npujarec5762e2020-01-01 14:08:48 +05301721 if err := dh.clearNNIData(ctx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001722 logger.Errorw(ctx, "failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001723 }
A R Karthick1f85b802019-10-11 05:06:05 +00001724
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001725 /* Clear the resource pool for each PON port in the background */
Kent Hagermane6ff1012020-07-14 15:07:53 -04001726 go func() {
1727 if err := dh.resourceMgr.Delete(ctx); err != nil {
1728 logger.Debug(ctx, err)
1729 }
1730 }()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001731 }
A R Karthick1f85b802019-10-11 05:06:05 +00001732
Devmalya Paul495b94a2019-08-27 19:42:00 -04001733 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301734 dh.onus.Range(func(key interface{}, value interface{}) bool {
1735 dh.onus.Delete(key)
1736 return true
1737 })
1738
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001739 /*Delete discovered ONU map for the device*/
1740 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1741 dh.discOnus.Delete(key)
1742 return true
1743 })
Devmalya Paul495b94a2019-08-27 19:42:00 -04001744}
1745
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001746//RebootDevice reboots the given device
Neha Sharma96b7bf22020-06-15 10:37:32 +00001747func (dh *DeviceHandler) RebootDevice(ctx context.Context, device *voltha.Device) error {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001748 if _, err := dh.Client.Reboot(log.WithSpanFromContext(context.Background(), ctx), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301749 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001750 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001751 logger.Debugw(ctx, "rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001752 return nil
1753}
1754
David K. Bainbridge794735f2020-02-11 21:01:37 -08001755func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001756 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001757 logger.Debugw(ctx, "received-packet-in", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001758 "packet-indication": *packetIn,
1759 "device-id": dh.device.Id,
1760 "packet": hex.EncodeToString(packetIn.Pkt),
1761 })
1762 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07001763 logicalPortNum, err := dh.flowMgr[packetIn.IntfId].GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001764 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001765 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001766 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001767 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001768 logger.Debugw(ctx, "sending-packet-in-to-core", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001769 "logical-port-num": logicalPortNum,
1770 "device-id": dh.device.Id,
1771 "packet": hex.EncodeToString(packetIn.Pkt),
1772 })
1773 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001774
Neha Sharma8f4e4322020-08-06 10:51:53 +00001775 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 +05301776 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001777 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301778 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001779 "device-id": dh.device.Id,
1780 "packet": hex.EncodeToString(packetIn.Pkt),
1781 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001782 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001783
Matteo Scandolo92186242020-06-12 10:54:18 -07001784 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001785 logger.Debugw(ctx, "success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001786 "packet": hex.EncodeToString(packetIn.Pkt),
1787 "device-id": dh.device.Id,
1788 })
1789 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001790 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001791}
1792
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001793// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301794func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001795 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001796 logger.Debugw(ctx, "incoming-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001797 "device-id": dh.device.Id,
1798 "egress-port-no": egressPortNo,
1799 "pkt-length": len(packet.Data),
1800 "packet": hex.EncodeToString(packet.Data),
1801 })
1802 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001803
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001804 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001805 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001806 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1807 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301808 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1809 // Do not packet-out lldp packets on uni port.
1810 // ONOS has no clue about uni/nni ports, it just packets out on all
1811 // available ports on the Logical Switch. It should not be interested
1812 // in the UNI links.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001813 logger.Debugw(ctx, "dropping-lldp-packet-out-on-uni", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001814 "device-id": dh.device.Id,
1815 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301816 return nil
1817 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001818 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1819 if innerEthType == 0x8100 {
1820 // q-in-q 802.1ad or 802.1q double tagged packet.
1821 // slice out the outer tag.
1822 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001823 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001824 logger.Debugw(ctx, "packet-now-single-tagged", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001825 "packet-data": hex.EncodeToString(packet.Data),
1826 "device-id": dh.device.Id,
1827 })
1828 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001829 }
1830 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001831 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1832 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001833 uniID := UniIDFromPortNum(uint32(egressPortNo))
1834
Girish Gowdra9602eb42020-09-09 15:50:39 -07001835 gemPortID, err := dh.flowMgr[intfID].GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001836 if err != nil {
1837 // In this case the openolt agent will receive the gemPortID as 0.
1838 // The agent tries to retrieve the gemPortID in this case.
1839 // This may not always succeed at the agent and packetOut may fail.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001840 logger.Errorw(ctx, "failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001841 "intf-id": intfID,
1842 "onu-id": onuID,
1843 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001844 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301845 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001846 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001847 }
1848
1849 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matteo Scandolo92186242020-06-12 10:54:18 -07001850 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001851 logger.Debugw(ctx, "sending-packet-to-onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001852 "egress-port-no": egressPortNo,
1853 "intf-id": intfID,
1854 "onu-id": onuID,
1855 "uni-id": uniID,
1856 "gem-port-id": gemPortID,
1857 "packet": hex.EncodeToString(packet.Data),
1858 "device-id": dh.device.Id,
1859 })
1860 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001861
npujarec5762e2020-01-01 14:08:48 +05301862 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301863 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001864 "source": "adapter",
1865 "destination": "onu",
1866 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001867 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001868 "oni-id": onuID,
1869 "uni-id": uniID,
1870 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001871 "packet": hex.EncodeToString(packet.Data),
1872 "device-id": dh.device.Id,
1873 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001874 }
1875 } else if egressPortType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001876 nniIntfID, err := IntfIDFromNniPortNum(ctx, uint32(egressPortNo))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001877 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001878 return olterrors.NewErrInvalidValue(log.Fields{
1879 "egress-nni-port": egressPortNo,
1880 "device-id": dh.device.Id,
1881 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001882 }
1883 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001884
Matteo Scandolo92186242020-06-12 10:54:18 -07001885 if logger.V(log.DebugLevel) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001886 logger.Debugw(ctx, "sending-packet-to-nni", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001887 "uplink-pkt": uplinkPkt,
1888 "packet": hex.EncodeToString(packet.Data),
1889 "device-id": dh.device.Id,
1890 })
1891 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001892
npujarec5762e2020-01-01 14:08:48 +05301893 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001894 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1895 "packet": hex.EncodeToString(packet.Data),
1896 "device-id": dh.device.Id,
1897 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001898 }
1899 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001900 logger.Warnw(ctx, "packet-out-to-this-interface-type-not-implemented", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301901 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001902 "egressPortType": egressPortType,
1903 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301904 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001905 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001906 }
1907 return nil
1908}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001909
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001910func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1911 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001912}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301913
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001914func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Neha Sharma8f4e4322020-08-06 10:51:53 +00001915
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301916 // start the heartbeat check towards the OLT.
1917 var timerCheck *time.Timer
1918
1919 for {
1920 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1921 select {
1922 case <-heartbeatTimer.C:
Neha Sharma8f4e4322020-08-06 10:51:53 +00001923 ctxWithTimeout, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), dh.openOLT.GrpcTimeoutInterval)
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001924 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001925 logger.Warnw(ctx, "hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301926 if timerCheck == nil {
1927 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001928 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301929 }
1930 } else {
1931 if timerCheck != nil {
1932 if timerCheck.Stop() {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001933 logger.Debugw(ctx, "got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301934 }
1935 timerCheck = nil
1936 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001937 logger.Debugw(ctx, "hearbeat",
Shrey Baid807a2a02020-04-09 12:52:45 +05301938 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301939 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301940 }
1941 cancel()
1942 case <-dh.stopHeartbeatCheck:
Neha Sharma96b7bf22020-06-15 10:37:32 +00001943 logger.Debugw(ctx, "stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301944 return
1945 }
1946 }
1947}
1948
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001949func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1950 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1951 if err != nil || device == nil {
Girish Gowdrab1caa442020-10-19 12:24:39 -07001952 // One case where we have seen core returning an error for GetDevice call is after OLT device delete.
1953 // After OLT delete, the adapter asks for OLT to reboot. When OLT is rebooted, shortly we loose heartbeat.
1954 // The 'startHeartbeatCheck' then asks the device to be marked unreachable towards the core, but the core
1955 // has already deleted the device and returns error. In this particular scenario, it is Ok because any necessary
1956 // cleanup in the adapter was already done during DeleteDevice API handler routine.
Kent Hagermane6ff1012020-07-14 15:07:53 -04001957 _ = olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
Girish Gowdrab1caa442020-10-19 12:24:39 -07001958 // Immediately return, otherwise accessing a null 'device' struct would cause panic
1959 return
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001960 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301961
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001962 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1963 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001964 _ = 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 -04001965 }
Kent Hagermanf1db18b2020-07-08 13:38:15 -04001966 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, 0, voltha.OperStatus_UNKNOWN); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001967 _ = olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001968 }
Gamze Abaka07868a52020-12-17 14:19:28 +00001969
1970 //raise olt communication failure event
1971 raisedTs := time.Now().UnixNano()
1972 device.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1973 device.OperStatus = voltha.OperStatus_UNKNOWN
1974 go dh.eventMgr.oltCommunicationEvent(ctx, device, raisedTs)
1975
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001976 go dh.cleanupDeviceResources(ctx)
1977
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001978 dh.lockDevice.RLock()
1979 // Stop the read indication only if it the routine is active
1980 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1981 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1982 // on next execution of the readIndication routine.
1983 if dh.isReadIndicationRoutineActive {
1984 dh.stopIndications <- true
1985 }
1986 dh.lockDevice.RUnlock()
1987
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001988 dh.transitionMap.Handle(ctx, DeviceInit)
1989
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301990 }
1991}
kesavand39e0aa32020-01-28 20:58:50 -05001992
1993// EnablePort to enable Pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00001994func (dh *DeviceHandler) EnablePort(ctx context.Context, port *voltha.Port) error {
1995 logger.Debugw(ctx, "enable-port", log.Fields{"Device": dh.device, "port": port})
1996 return dh.modifyPhyPort(ctx, port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001997}
1998
1999// DisablePort to disable pon interface
Neha Sharma96b7bf22020-06-15 10:37:32 +00002000func (dh *DeviceHandler) DisablePort(ctx context.Context, port *voltha.Port) error {
2001 logger.Debugw(ctx, "disable-port", log.Fields{"Device": dh.device, "port": port})
2002 return dh.modifyPhyPort(ctx, port, false)
kesavand39e0aa32020-01-28 20:58:50 -05002003}
2004
kdarapu1afeceb2020-02-12 01:38:09 -05002005//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002006func (dh *DeviceHandler) modifyPhyPort(ctx context.Context, port *voltha.Port, enablePort bool) error {
2007 logger.Infow(ctx, "modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05002008 if port.GetType() == voltha.Port_ETHERNET_NNI {
2009 // Bug is opened for VOL-2505 to support NNI disable feature.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002010 logger.Infow(ctx, "voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05302011 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05302012 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002013 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00002014 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05002015 }
2016 // fetch interfaceid from PortNo
2017 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
2018 ponIntf := &oop.Interface{IntfId: ponID}
2019 var operStatus voltha.OperStatus_Types
2020 if enablePort {
2021 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05302022 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002023
2024 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302025 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002026 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002027 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002028 }
2029 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002030 dh.activePorts.Store(ponID, true)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002031 logger.Infow(ctx, "enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002032 } else {
2033 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05302034 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05002035 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302036 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002037 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002038 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002039 }
2040 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05002041 dh.activePorts.Store(ponID, false)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002042 logger.Infow(ctx, "disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05002043 }
Thomas Lee S985938d2020-05-04 11:40:41 +05302044 if err := dh.coreProxy.PortStateUpdate(ctx, dh.device.Id, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302045 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302046 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002047 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002048 }
2049 return nil
2050}
2051
kdarapu1afeceb2020-02-12 01:38:09 -05002052//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002053func (dh *DeviceHandler) disableAdminDownPorts(ctx context.Context, ports []*voltha.Port) error {
kesavand39e0aa32020-01-28 20:58:50 -05002054 // Disable the port and update the oper_port_status to core
2055 // if the Admin state of the port is disabled on reboot and re-enable device.
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002056 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002057 if port.AdminState == common.AdminState_DISABLED {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002058 if err := dh.DisablePort(ctx, port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302059 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302060 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002061 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002062 }
2063 }
2064 }
2065 return nil
2066}
2067
2068//populateActivePorts to populate activePorts map
Kent Hagermanf1db18b2020-07-08 13:38:15 -04002069func (dh *DeviceHandler) populateActivePorts(ctx context.Context, ports []*voltha.Port) {
2070 logger.Infow(ctx, "populateActivePorts", log.Fields{"device-id": dh.device.Id})
2071 for _, port := range ports {
kesavand39e0aa32020-01-28 20:58:50 -05002072 if port.Type == voltha.Port_ETHERNET_NNI {
2073 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002074 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002075 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002076 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002077 }
2078 }
2079 if port.Type == voltha.Port_PON_OLT {
2080 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002081 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002082 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002083 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002084 }
2085 }
2086 }
2087}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002088
2089// ChildDeviceLost deletes ONU and clears pon resources related to it.
2090func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
divyadesai3af43e12020-08-18 07:10:54 +00002091 logger.Debugw(ctx, "child-device-lost", log.Fields{"parent-device-id": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002092 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2093 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002094 onuDevice, ok := dh.onus.Load(onuKey)
2095 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302096 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002097 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002098 "device-id": dh.device.Id,
2099 "onu-id": onuID,
2100 "intf-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002101 }
2102 var sn *oop.SerialNumber
2103 var err error
2104 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302105 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002106 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302107 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002108 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2109 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002110
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002111 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Neha Sharma8f4e4322020-08-06 10:51:53 +00002112 if _, err := dh.Client.DeleteOnu(log.WithSpanFromContext(context.Background(), ctx), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302113 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302114 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002115 "onu-id": onuID}, err).Log()
2116 }
2117 //clear PON resources associated with ONU
2118 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002119 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002120 logger.Warnw(ctx, "failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002121 "device-id": dh.device.Id,
2122 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002123 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002124 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125 logger.Warnw(ctx, "failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002126 "device-id": dh.device.Id,
2127 "intf-id": intfID,
2128 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002129 } else {
2130 for i, onu := range onuGemData {
2131 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002132 logger.Debugw(ctx, "onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002133 if err := dh.clearUNIData(ctx, &onu); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002134 logger.Warnw(ctx, "failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302135 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002136 "onu-device": onu,
2137 "error": err})
2138 }
2139 // Clear flowids for gem cache.
2140 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002141 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002142 }
2143 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002144 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002145 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002146 logger.Warnw(ctx, "persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002147 "intf-id": intfID,
2148 "onu-device": onu,
2149 "onu-gem": onuGemData,
2150 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002151 //Not returning error on cleanup.
2152 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002153 logger.Debugw(ctx, "removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002154 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002155 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002156 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002157 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002158 }
2159 }
2160 dh.onus.Delete(onuKey)
2161 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002162 dh.removeOnuIndicationChannels(ctx, onuDevice.(*OnuDevice).serialNumber)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002163 return nil
2164}
Girish Gowdracefae192020-03-19 18:14:10 -07002165
2166func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2167 for _, field := range flows.GetOfbFields(flow) {
2168 if field.Type == flows.IN_PORT {
2169 return field.GetPort()
2170 }
2171 }
2172 return InvalidPort
2173}
2174
2175func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2176 for _, action := range flows.GetActions(flow) {
2177 if action.Type == flows.OUTPUT {
2178 if out := action.GetOutput(); out != nil {
2179 return out.GetPort()
2180 }
2181 }
2182 }
2183 return InvalidPort
2184}
2185
Girish Gowdracefae192020-03-19 18:14:10 -07002186func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2187 inPort := getInPortFromFlow(flow)
2188 outPort := getOutPortFromFlow(flow)
2189
2190 if inPort == InvalidPort || outPort == InvalidPort {
2191 return inPort, outPort
2192 }
2193
2194 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2195 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2196 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2197 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2198 return uniPort, outPort
2199 }
2200 }
2201 } else {
2202 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2203 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2204 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2205 return inPort, uniPort
2206 }
2207 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2208 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2209 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2210 return uniPort, outPort
2211 }
2212 }
2213 }
2214
2215 return InvalidPort, InvalidPort
2216}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002217
2218func extractOmciTransactionID(omciPkt []byte) uint16 {
2219 if len(omciPkt) > 3 {
2220 d := omciPkt[0:2]
2221 transid := binary.BigEndian.Uint16(d)
2222 return transid
2223 }
2224 return 0
2225}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002226
2227// StoreOnuDevice stores the onu parameters to the local cache.
2228func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2229 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2230 dh.onus.Store(onuKey, onuDevice)
2231}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002232
Neha Sharma8f4e4322020-08-06 10:51:53 +00002233func (dh *DeviceHandler) getExtValue(ctx context.Context, device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002234 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002235 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002236 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002237 resp := new(voltha.ReturnValues)
2238 valueparam := new(oop.ValueParam)
Neha Sharma8f4e4322020-08-06 10:51:53 +00002239 ctx = log.WithSpanFromContext(context.Background(), ctx)
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002240 logger.Infow(ctx, "getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002241 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2242 return nil, err
2243 }
2244 ID = device.ProxyAddress.GetOnuId()
2245 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2246 valueparam.Onu = &Onu
2247 valueparam.Value = value
2248
2249 // This API is unsupported until agent patch is added
2250 resp.Unsupported = uint32(value)
2251 _ = ctx
2252
2253 // Uncomment this code once agent changes are complete and tests
2254 /*
2255 resp, err = dh.Client.GetValue(ctx, valueparam)
2256 if err != nil {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002257 logger.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002258 return nil, err
2259 }
2260 */
2261
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002262 logger.Infow(ctx, "get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002263 return resp, nil
2264}
Girish Gowdra9602eb42020-09-09 15:50:39 -07002265
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002266func (dh *DeviceHandler) getPonIfFromFlow(flow *of.OfpFlowStats) uint32 {
Girish Gowdra9602eb42020-09-09 15:50:39 -07002267 // Default to PON0
2268 var intfID uint32
2269 inPort, outPort := getPorts(flow)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002270 if inPort != InvalidPort && outPort != InvalidPort {
2271 _, intfID, _, _ = ExtractAccessFromFlow(inPort, outPort)
2272 }
2273 return intfID
2274}
Mahir Gunyel2fb81472020-12-16 23:18:34 -08002275
2276func (dh *DeviceHandler) getOnuIndicationChannel(ctx context.Context, sn string) chan perOnuIndication {
2277 dh.perOnuChannelLock.Lock()
2278 if ch, ok := dh.perOnuChannel[sn]; ok {
2279 dh.perOnuChannelLock.Unlock()
2280 return ch.indicationChannel
2281 }
2282 channels := onuIndicationChannels{
2283 //We create a buffered channel here to avoid calling function to be blocked
2284 //in case of multiple indications from the same ONU,
2285 //especially in the case where indications are buffered in OLT.
2286 indicationChannel: make(chan perOnuIndication, 5),
2287 stopChannel: make(chan struct{}),
2288 }
2289 dh.perOnuChannel[sn] = channels
2290 dh.perOnuChannelLock.Unlock()
2291 go dh.perOnuIndicationsRoutine(&channels)
2292 return channels.indicationChannel
2293
2294}
2295
2296func (dh *DeviceHandler) removeOnuIndicationChannels(ctx context.Context, sn string) {
2297 logger.Debugw(ctx, "remove-onu-indication-channels", log.Fields{"sn": sn})
2298 dh.perOnuChannelLock.Lock()
2299 defer dh.perOnuChannelLock.Unlock()
2300 if ch, ok := dh.perOnuChannel[sn]; ok {
2301 close(ch.stopChannel)
2302 delete(dh.perOnuChannel, sn)
2303 }
2304
2305}
2306
2307func (dh *DeviceHandler) putOnuIndicationToChannel(ctx context.Context, indication *oop.Indication, sn string) {
2308 ind := perOnuIndication{
2309 ctx: ctx,
2310 indication: indication,
2311 serialNumber: sn,
2312 }
2313 logger.Debugw(ctx, "put-onu-indication-to-channel", log.Fields{"indication": indication, "sn": sn})
2314 // Send the onuIndication on the ONU channel
2315 dh.getOnuIndicationChannel(ctx, sn) <- ind
2316}
2317
2318func (dh *DeviceHandler) perOnuIndicationsRoutine(onuChannels *onuIndicationChannels) {
2319 for {
2320 select {
2321 // process one indication per onu, before proceeding to the next one
2322 case onuInd := <-onuChannels.indicationChannel:
2323 logger.Debugw(onuInd.ctx, "calling-indication", log.Fields{"device-id": dh.device.Id,
2324 "ind": onuInd.indication, "sn": onuInd.serialNumber})
2325 switch onuInd.indication.Data.(type) {
2326 case *oop.Indication_OnuInd:
2327 if err := dh.onuIndication(onuInd.ctx, onuInd.indication.GetOnuInd(), onuInd.serialNumber); err != nil {
2328 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2329 "type": "onu-indication",
2330 "device-id": dh.device.Id,
2331 "sn": onuInd.serialNumber}, err).Log()
2332 }
2333 case *oop.Indication_OnuDiscInd:
2334 if err := dh.onuDiscIndication(onuInd.ctx, onuInd.indication.GetOnuDiscInd(), onuInd.serialNumber); err != nil {
2335 _ = olterrors.NewErrAdapter("handle-indication-error", log.Fields{
2336 "type": "onu-discovery",
2337 "device-id": dh.device.Id,
2338 "sn": onuInd.serialNumber}, err).Log()
2339 }
2340 }
2341 case <-onuChannels.stopChannel:
2342 logger.Debugw(context.Background(), "stop-signal-received-for-onu-channel", log.Fields{"device-id": dh.device.Id})
2343 close(onuChannels.indicationChannel)
2344 return
2345 }
2346 }
2347}