blob: a5b131daf4feaa7fd91808b68d826599c76facd0 [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
Shrey Baid807a2a02020-04-09 12:52:45 +053032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33
Matteo Scandolo945e4012019-12-12 14:16:11 -080034 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070035 "github.com/gogo/protobuf/proto"
36 "github.com/golang/protobuf/ptypes"
Esin Karamanccb714b2019-11-29 15:02:06 +000037 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
38 "github.com/opencord/voltha-lib-go/v3/pkg/log"
39 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Thomas Lee S94109f12020-03-03 16:39:29 +053040 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080041 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000042 "github.com/opencord/voltha-protos/v3/go/common"
43 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
44 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
45 oop "github.com/opencord/voltha-protos/v3/go/openolt"
46 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070047 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040048 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040049 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053050)
51
salmansiddiqui7ac62132019-08-22 03:58:50 +000052// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040053const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000054 MaxRetry = 10
55 MaxTimeOutInMs = 500
Girish Gowdracefae192020-03-19 18:14:10 -070056 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040057)
58
Girish Gowdracefae192020-03-19 18:14:10 -070059// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
60type pendingFlowRemoveDataKey struct {
61 intfID uint32
62 onuID uint32
63 uniID uint32
64}
65
66// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
67// This holds the number of pending flow removes and also a signal channel to
68// to indicate the receiver when all flow removes are handled
69type pendingFlowRemoveData struct {
70 pendingFlowRemoveCount uint32
71 allFlowsRemoved chan struct{}
72}
73
Phaneendra Manda4c62c802019-03-06 21:37:49 +053074//DeviceHandler will interact with the OLT device.
75type DeviceHandler struct {
cuilin20187b2a8c32019-03-26 19:52:28 -070076 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053077 coreProxy adapterif.CoreProxy
78 AdapterProxy adapterif.AdapterProxy
79 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070080 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070081 exitChannel chan int
82 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053083 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070084 transitionMap *TransitionMap
85 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053086 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040087 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053088 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053089
Girish Gowdra3ab6d212020-03-24 17:33:15 -070090 discOnus sync.Map
91 onus sync.Map
92 portStats *OpenOltStatisticsMgr
93 metrics *pmmetrics.PmMetrics
94 stopCollector chan bool
95 stopHeartbeatCheck chan bool
96 activePorts sync.Map
97 stopIndications chan bool
98 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -070099
100 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
101 // subscriber basis for the number of pending flow removes. This data is used
102 // to process all the flow removes for a subscriber before handling flow adds.
103 // Interleaving flow delete and flow add processing has known to cause PON resource
104 // management contentions on a per subscriber bases, so we need ensure ordering.
105 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700106}
107
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700111 deviceType string
112 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 onuID uint32
114 intfID uint32
115 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +0000116 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530117 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400118 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700119}
120
Naga Manjunath7615e552019-10-11 22:35:47 +0530121var pmNames = []string{
122 "rx_bytes",
123 "rx_packets",
124 "rx_mcast_packets",
125 "rx_bcast_packets",
126 "tx_bytes",
127 "tx_packets",
128 "tx_mcast_packets",
129 "tx_bcast_packets",
130}
131
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700132//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530133func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700135 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700136 device.deviceType = deviceTp
137 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700138 device.onuID = onuID
139 device.intfID = intfID
140 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000141 device.uniPorts = make(map[uint32]struct{})
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530142 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700143 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530144}
145
146//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530147func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700148 var dh DeviceHandler
149 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400150 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400151 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700152 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700153 dh.device = cloned
154 dh.openOLT = adapter
155 dh.exitChannel = make(chan int, 1)
156 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530157 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530158 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530159 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500160 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400161 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700162 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
163
cuilin20187b2a8c32019-03-26 19:52:28 -0700164 //TODO initialize the support classes.
165 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530166}
167
168// start save the device to the data model
169func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700170 dh.lockDevice.Lock()
171 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000172 logger.Debugw("starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700173 // Add the initial device to the local model
Girish Kumar2ad402b2020-03-20 19:45:12 +0000174 logger.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530175}
176
177// stop stops the device dh. Not much to do for now
178func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700179 dh.lockDevice.Lock()
180 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000181 logger.Debug("stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700182 dh.exitChannel <- 1
Girish Kumar2ad402b2020-03-20 19:45:12 +0000183 logger.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530184}
185
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400186func macifyIP(ip net.IP) string {
187 if len(ip) > 0 {
188 oct1 := strconv.FormatInt(int64(ip[12]), 16)
189 oct2 := strconv.FormatInt(int64(ip[13]), 16)
190 oct3 := strconv.FormatInt(int64(ip[14]), 16)
191 oct4 := strconv.FormatInt(int64(ip[15]), 16)
192 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
193 }
194 return ""
195}
196
197func generateMacFromHost(host string) (string, error) {
198 var genmac string
199 var addr net.IP
200 var ips []string
201 var err error
202
Girish Kumar2ad402b2020-03-20 19:45:12 +0000203 logger.Debugw("generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400204
205 if addr = net.ParseIP(host); addr == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000206 logger.Debugw("looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400207
208 if ips, err = net.LookupHost(host); err == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000209 logger.Debugw("dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400210 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000211 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400212 }
213 genmac = macifyIP(addr)
Shrey Baid807a2a02020-04-09 12:52:45 +0530214 logger.Debugw("using-ip-as-mac",
215 log.Fields{"host": ips[0],
216 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400217 return genmac, nil
218 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000219 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400220 }
221
222 genmac = macifyIP(addr)
Shrey Baid807a2a02020-04-09 12:52:45 +0530223 logger.Debugw("using-ip-as-mac",
224 log.Fields{"host": host,
225 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400226 return genmac, nil
227}
228
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530229func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700230 slist := strings.Split(mac, ":")
231 result := make([]uint32, len(slist))
232 var err error
233 var tmp int64
234 for index, val := range slist {
235 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
236 return []uint32{1, 2, 3, 4, 5, 6}
237 }
238 result[index] = uint32(tmp)
239 }
240 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530241}
242
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700243//GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800244func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530245
David K. Bainbridge794735f2020-02-11 21:01:37 -0800246 switch portType {
247 case voltha.Port_ETHERNET_NNI:
248 return fmt.Sprintf("nni-%d", portNum), nil
249 case voltha.Port_PON_OLT:
250 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700251 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800252
Girish Kumarf26e4882020-03-05 06:49:10 +0000253 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530254}
255
David K. Bainbridge794735f2020-02-11 21:01:37 -0800256func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000257 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700258 if state == "up" {
259 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500260 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500261 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700262 } else {
263 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500264 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700265 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700266 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400267 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800268 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000269 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400270 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500271
272 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
273 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000274 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500275 }
276 if device.Ports != nil {
277 for _, dPort := range device.Ports {
278 if dPort.Type == portType && dPort.PortNo == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000279 logger.Debug("port-already-exists-updating-oper-status-of-port")
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500280 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530281 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800282 "device-id": dh.device.Id,
283 "port-type": portType,
284 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000285 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800286
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500287 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800288 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500289 }
290 }
291 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400292 // Now create Port
293 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700294 PortNo: portNum,
295 Label: label,
296 Type: portType,
297 OperStatus: operStatus,
298 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530299 logger.Debugw("sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700300 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700301 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000302 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800303 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000304 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400305 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530306 go dh.updateLocalDevice()
307 return nil
308}
309
310func (dh *DeviceHandler) updateLocalDevice() error {
311 dh.lockDevice.Lock()
312 defer dh.lockDevice.Unlock()
313 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
314 if err != nil || device == nil {
315 logger.Errorf("device", log.Fields{"device-id": dh.device.Id}, err)
316 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
317 }
318 dh.device = device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800319 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530320}
321
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700322// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530323// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800324func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000325 defer logger.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700326 defer func() {
327 dh.lockDevice.Lock()
328 dh.isReadIndicationRoutineActive = false
329 dh.lockDevice.Unlock()
330 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700331 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700332 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700333 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700334 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400335 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530336 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400337 if err != nil || device == nil {
338 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000339 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400340 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400341
David Bainbridgef5879ca2019-12-13 21:17:54 +0000342 // Create an exponential backoff around re-enabling indications. The
343 // maximum elapsed time for the back off is set to 0 so that we will
344 // continue to retry. The max interval defaults to 1m, but is set
345 // here for code clarity
346 indicationBackoff := backoff.NewExponentialBackOff()
347 indicationBackoff.MaxElapsedTime = 0
348 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700349
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700350 dh.lockDevice.Lock()
351 dh.isReadIndicationRoutineActive = true
352 dh.lockDevice.Unlock()
353
Girish Gowdra3f974912020-03-23 20:35:18 -0700354Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700355 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400356 select {
357 case <-dh.stopIndications:
Thomas Lee S985938d2020-05-04 11:40:41 +0530358 logger.Debugw("stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700359 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400360 default:
361 indication, err := indications.Recv()
362 if err == io.EOF {
Shrey Baid807a2a02020-04-09 12:52:45 +0530363 logger.Infow("eof-for-indications",
364 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530365 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400366 // Use an exponential back off to prevent getting into a tight loop
367 duration := indicationBackoff.NextBackOff()
368 if duration == backoff.Stop {
369 // If we reach a maximum then warn and reset the backoff
370 // timer and keep attempting.
Shrey Baid807a2a02020-04-09 12:52:45 +0530371 logger.Warnw("maximum-indication-backoff-reached--resetting-backoff-timer",
372 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530373 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400374 indicationBackoff.Reset()
375 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700376
377 // On failure process a backoff timer while watching for stopIndications
378 // events
379 backoff := time.NewTimer(indicationBackoff.NextBackOff())
380 select {
381 case <-dh.stopIndications:
382 logger.Debugw("stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
383 if !backoff.Stop() {
384 <-backoff.C
385 }
386 break Loop
387 case <-backoff.C:
388 // backoff expired continue
389 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700390 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
391 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400392 }
393 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000394 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530395 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530396 logger.Errorw("read-indication-error",
397 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530398 "device-id": dh.device.Id})
399 if device.AdminState == voltha.AdminState_DELETED {
Shrey Baid807a2a02020-04-09 12:52:45 +0530400 logger.Debug("device-deleted--stopping-the-read-indication-thread")
Girish Gowdra3f974912020-03-23 20:35:18 -0700401 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400402 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700403 // Close the stream, and re-initialize it
404 if err = indications.CloseSend(); err != nil {
405 // Ok to ignore here, because we landed here due to a problem on the stream
406 // In all probability, the closeSend call may fail
Shrey Baid807a2a02020-04-09 12:52:45 +0530407 logger.Debugw("error-closing-send stream--error-ignored",
408 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530409 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700410 }
411 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
412 return err
413 }
414 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400415 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530416 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400417 // Reset backoff if we have a successful receive
418 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400419 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530420 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530421 logger.Debugw("olt-is-admin-down, ignore indication",
422 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530423 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400424 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400425 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400426 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700427 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700428 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700429 // Close the send stream
430 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700431
Girish Gowdra3f974912020-03-23 20:35:18 -0700432 return nil
433}
434
435func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
436
437 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
438 if err != nil {
439 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
440 }
441 if indications == nil {
442 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
443 }
444
445 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400446}
447
448// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
449func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
450 switch indication.Data.(type) {
451 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
452 return true
453
454 default:
455 return false
456 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700457}
458
David K. Bainbridge794735f2020-02-11 21:01:37 -0800459func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000460 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000461 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530462 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700463 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530464 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700465 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000466 // Send or clear Alarm
Thomas Lee S985938d2020-05-04 11:40:41 +0530467 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530468 return olterrors.NewErrAdapter("failed-indication", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530469 "device_id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800470 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000471 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800472 }
473 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700474}
475
David K. Bainbridge794735f2020-02-11 21:01:37 -0800476// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530477func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400478 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700479 switch indication.Data.(type) {
480 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530482 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800483 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700484 case *oop.Indication_IntfInd:
485 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800486 go func() {
487 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530488 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800489 }
490 }()
Thomas Lee S985938d2020-05-04 11:40:41 +0530491 logger.Infow("received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700492 case *oop.Indication_IntfOperInd:
493 intfOperInd := indication.GetIntfOperInd()
494 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800495 go func() {
496 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530497 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 -0800498 }
499 }()
npujarec5762e2020-01-01 14:08:48 +0530500 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700501 } else if intfOperInd.GetType() == "pon" {
502 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
503 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800504 go func() {
505 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530506 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 -0800507 }
508 }()
Thomas Lee S985938d2020-05-04 11:40:41 +0530509 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700510 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530511 logger.Infow("received-interface-oper-indication",
512 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530513 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700514 case *oop.Indication_OnuDiscInd:
515 onuDiscInd := indication.GetOnuDiscInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530516 logger.Infow("received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700517 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800518 go func() {
519 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530520 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800521 }
522 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700523 case *oop.Indication_OnuInd:
524 onuInd := indication.GetOnuInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530525 logger.Infow("received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800526 go func() {
527 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530528 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800529 }
530 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700531 case *oop.Indication_OmciInd:
532 omciInd := indication.GetOmciInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530533 logger.Debugw("received-omci-indication", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800534 go func() {
535 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530536 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800537 }
538 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700539 case *oop.Indication_PktInd:
540 pktInd := indication.GetPktInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530541 logger.Infow("received-packet-indication", log.Fields{"PktInd": pktInd, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800542 go func() {
543 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530544 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800545 }
546 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700547 case *oop.Indication_PortStats:
548 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530549 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700550 case *oop.Indication_FlowStats:
551 flowStats := indication.GetFlowStats()
Thomas Lee S985938d2020-05-04 11:40:41 +0530552 logger.Infow("received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700553 case *oop.Indication_AlarmInd:
554 alarmInd := indication.GetAlarmInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530555 logger.Infow("received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
556 go dh.eventMgr.ProcessEvents(alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700557 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530558}
559
560// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530561func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530562 //starting the stat collector
563 go startCollector(dh)
564
Girish Gowdru0c588b22019-04-23 23:24:56 -0400565 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530566 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400567 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000568 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400569 }
570 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530571}
572
573// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530574func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700575 dh.lockDevice.Lock()
576 defer dh.lockDevice.Unlock()
Thomas Lee S985938d2020-05-04 11:40:41 +0530577 logger.Debugw("do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400578
npujarec5762e2020-01-01 14:08:48 +0530579 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400580 if err != nil || device == nil {
581 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000582 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400583 }
584
585 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400586
587 //Update the device oper state and connection status
588 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400589 dh.device = cloned
590
David K. Bainbridge794735f2020-02-11 21:01:37 -0800591 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000592 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400593 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400594
595 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530596 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400597 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000598 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400599 }
600 for _, onuDevice := range onuDevices.Items {
601
602 // Update onu state as down in onu adapter
603 onuInd := oop.OnuIndication{}
604 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800605 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700606 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800607 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530608 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800609 "source": "openolt",
610 "onu-indicator": onuInd,
611 "device-type": onuDevice.Type,
612 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700613 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700614 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400615 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700616 /* Discovered ONUs entries need to be cleared , since after OLT
617 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530618 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000619 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700620 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530621}
622
623// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530624func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400625 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800626 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530627 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530628 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000629 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400630 }
631 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530632}
633
634// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530635func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400636 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530637 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400638 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530639}
640
641// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530642func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530643 var err error
644 logger.Debugw("olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400645
646 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530647 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
648 if err != nil || device == nil {
649 /*TODO: needs to handle error scenarios */
650 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
651 }
652 if device.AdminState == voltha.AdminState_DISABLED {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000653 logger.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400654
655 cloned := proto.Clone(device).(*voltha.Device)
656 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
657 cloned.OperStatus = voltha.OperStatus_UNKNOWN
658 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530659 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
660 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 -0400661 }
662
Chaitrashree G S44124192019-08-07 20:21:36 -0400663 // 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 +0530664 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400665 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530666 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400667 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400668 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
669 // all the modules initialized and ready to handle incoming ONUs.
670
Thomas Lee S985938d2020-05-04 11:40:41 +0530671 err = dh.initializeDeviceHandlerModules(ctx)
672 if err != nil {
673 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 -0400674 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400675
676 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800677 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530678 if err = dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530679 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800680 }
681 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400682 return nil
683 }
684
Thomas Lee S985938d2020-05-04 11:40:41 +0530685 device, err = dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400686 if err != nil || device == nil {
687 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000688 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400689 }
kesavand39e0aa32020-01-28 20:58:50 -0500690 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500691 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000692 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400693 }
694
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400695 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530696 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 -0400697 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530698
cuilin20187b2a8c32019-03-26 19:52:28 -0700699 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800700 go func() {
701 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530702 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800703 }
704 }()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530705 go dh.updateLocalDevice()
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000706
707 if device.PmConfigs != nil {
708 dh.UpdatePmConfig(device.PmConfigs)
709 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700710 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530711}
712
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400713func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
714 deviceInfo, err := dh.populateDeviceInfo()
715
716 if err != nil {
717 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
718 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400719 // Instantiate resource manager
Neha Sharma3f221ae2020-04-29 19:02:12 +0000720 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, deviceInfo); dh.resourceMgr == nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400721 return olterrors.ErrResourceManagerInstantiating
722 }
723
724 // Instantiate flow manager
725 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
726 return olterrors.ErrResourceManagerInstantiating
727
728 }
729 /* TODO: Instantiate Alarm , stats , BW managers */
730 /* Instantiating Event Manager to handle Alarms and KPIs */
731 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
732
733 // Stats config for new device
734 dh.portStats = NewOpenOltStatsMgr(dh)
735
736 return nil
737
738}
739
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400740func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
741 var err error
742 var deviceInfo *oop.DeviceInfo
743
744 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
745
746 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000747 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400748 }
749 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000750 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400751 }
752
Thomas Lee S985938d2020-05-04 11:40:41 +0530753 logger.Debugw("fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400754 dh.device.Root = true
755 dh.device.Vendor = deviceInfo.Vendor
756 dh.device.Model = deviceInfo.Model
757 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
758 dh.device.HardwareVersion = deviceInfo.HardwareVersion
759 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
760
761 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000762 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400763 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
764 genmac, err := generateMacFromHost(host)
765 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000766 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400767 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000768 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400769 dh.device.MacAddress = genmac
770 } else {
771 dh.device.MacAddress = deviceInfo.DeviceId
772 }
773
774 // Synchronous call to update device - this method is run in its own go routine
775 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000776 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400777 }
778
779 return deviceInfo, nil
780}
781
Naga Manjunath7615e552019-10-11 22:35:47 +0530782func startCollector(dh *DeviceHandler) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530783 logger.Debugf("starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530784 for {
785 select {
786 case <-dh.stopCollector:
Thomas Lee S985938d2020-05-04 11:40:41 +0530787 logger.Debugw("stopping-collector-for-olt", log.Fields{"deviceID:": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530788 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000789 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700790
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530791 ports := make([]*voltha.Port, len(dh.device.Ports))
792 copy(ports, dh.device.Ports)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530793 for _, port := range ports {
794 // NNI Stats
795 if port.Type == voltha.Port_ETHERNET_NNI {
796 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
797 cmnni := dh.portStats.collectNNIMetrics(intfID)
798 logger.Debugw("collect-nni-metrics", log.Fields{"metrics": cmnni})
Girish Gowdra34815db2020-05-11 17:18:04 -0700799 go dh.portStats.publishMetrics(cmnni, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530800 logger.Debugw("publish-nni-metrics", log.Fields{"nni-port": port.Label})
801 }
802 // PON Stats
803 if port.Type == voltha.Port_PON_OLT {
804 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
805 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
806 cmpon := dh.portStats.collectPONMetrics(intfID)
807 logger.Debugw("collect-pon-metrics", log.Fields{"metrics": cmpon})
Girish Gowdra34815db2020-05-11 17:18:04 -0700808 go dh.portStats.publishMetrics(cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530809 }
810 logger.Debugw("publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500811 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530812 }
813 }
814 }
815}
816
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700817//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530818func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400819 dh.transitionMap = NewTransitionMap(dh)
Shrey Baid807a2a02020-04-09 12:52:45 +0530820 logger.Infow("adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530821 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530822
823 // Now, set the initial PM configuration for that device
824 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530825 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530826 }
827
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400828 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530829}
830
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700831//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530832func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700833 return &ic.SwitchCapability{
834 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530835 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700836 HwDesc: "open_pon",
837 SwDesc: "open_pon",
838 SerialNum: dh.device.SerialNumber,
839 },
840 SwitchFeatures: &of.OfpSwitchFeatures{
841 NBuffers: 256,
842 NTables: 2,
843 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
844 of.OfpCapabilities_OFPC_TABLE_STATS |
845 of.OfpCapabilities_OFPC_PORT_STATS |
846 of.OfpCapabilities_OFPC_GROUP_STATS),
847 },
848 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530849}
850
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700851//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530852func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700853 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700854 return &ic.PortCapability{
855 Port: &voltha.LogicalPort{
856 OfpPort: &of.OfpPort{
857 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
858 Config: 0,
859 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700860 Curr: capacity,
861 Advertised: capacity,
862 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700863 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
864 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
865 },
866 DeviceId: dh.device.Id,
867 DevicePortNo: uint32(portNo),
868 },
869 }, nil
870}
871
David K. Bainbridge794735f2020-02-11 21:01:37 -0800872func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530873 logger.Debugw("omci-indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700874 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700875 var deviceID string
876 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700877
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400878 transid := extractOmciTransactionID(omciInd.Pkt)
Thomas Lee S985938d2020-05-04 11:40:41 +0530879 logger.Debugw("recv-omci-msg", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id,
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400880 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
881
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700882 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530883
884 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
885
Thomas Lee S985938d2020-05-04 11:40:41 +0530886 logger.Debugw("omci-indication-for-a-device-not-in-cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700887 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700888 kwargs := make(map[string]interface{})
889 kwargs["onu_id"] = omciInd.OnuId
890 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700891
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700892 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
893 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530894 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800895 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000896 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700897 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700898 deviceType = onuDevice.Type
899 deviceID = onuDevice.Id
900 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
901 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530902 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700903 } else {
904 //found in cache
Thomas Lee S985938d2020-05-04 11:40:41 +0530905 logger.Debugw("omci-indication-for-a-device-in-cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530906 deviceType = onuInCache.(*OnuDevice).deviceType
907 deviceID = onuInCache.(*OnuDevice).deviceID
908 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700909 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700910
911 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800912 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Thomas Lee S985938d2020-05-04 11:40:41 +0530913 ic.InterAdapterMessageType_OMCI_REQUEST, dh.device.Type, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800914 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530915 return olterrors.NewErrCommunication("omci-request", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530916 "source": dh.device.Type,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800917 "destination": deviceType,
918 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000919 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700920 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800921 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530922}
923
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700924//ProcessInterAdapterMessage sends the proxied messages to the target device
925// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
926// is meant, and then send the unmarshalled omci message to this onu
927func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530928 logger.Debugw("process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700929 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700930 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700931 fromTopic := msg.Header.FromTopic
932 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700933 toDeviceID := msg.Header.ToDeviceId
934 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700935
Shrey Baid807a2a02020-04-09 12:52:45 +0530936 logger.Debugw("omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700937
938 msgBody := msg.GetBody()
939
940 omciMsg := &ic.InterAdapterOmciMessage{}
941 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000942 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700943 }
944
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700945 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700946 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
947 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530948 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800949 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000950 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700951 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530952 logger.Debugw("device-retrieved-from-core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800953 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530954 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800955 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000956 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800957 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700958 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +0530959 logger.Debugw("proxy-address-found-in-omci-message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800960 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530961 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000963 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800964 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700965 }
966
967 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000968 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700969 }
970 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530971}
972
David K. Bainbridge794735f2020-02-11 21:01:37 -0800973func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700974 var intfID uint32
975 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000976 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700977 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700978 intfID = onuDevice.ProxyAddress.GetChannelId()
979 onuID = onuDevice.ProxyAddress.GetOnuId()
980 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700981 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700982 intfID = omciMsg.GetProxyAddress().GetChannelId()
983 onuID = omciMsg.GetProxyAddress().GetOnuId()
984 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700985 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700986 if connectStatus != voltha.ConnectStatus_REACHABLE {
Shrey Baid807a2a02020-04-09 12:52:45 +0530987 logger.Debugw("onu-not-reachable--cannot-send-omci", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800988
Thomas Lee S94109f12020-03-03 16:39:29 +0530989 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800990 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000991 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700992 }
993
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400994 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
995 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700996 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400997 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
998 hex.Encode(hexPkt, omciMsg.Message)
999 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1000
1001 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1002 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1003 transid := extractOmciTransactionID(omciMsg.Message)
1004 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
1005 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001006
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001007 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
1008 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301009 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001010 "interface-id": intfID,
1011 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001012 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001013 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001014 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001015}
1016
David K. Bainbridge794735f2020-02-11 21:01:37 -08001017func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301018 logger.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001019 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
1020 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
1021 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001022 // TODO: need resource manager
1023 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001024 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301025 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001026 st, _ := status.FromError(err)
1027 if st.Code() == codes.AlreadyExists {
Thomas Lee S985938d2020-05-04 11:40:41 +05301028 logger.Debugw("onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onuID": onuID, "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001029 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301030 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001031 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001032 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301033 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001034 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001035 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001036}
1037
David K. Bainbridge794735f2020-02-11 21:01:37 -08001038func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001039
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001040 channelID := onuDiscInd.GetIntfId()
1041 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001042
Girish Kumar2ad402b2020-03-20 19:45:12 +00001043 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301044
cuilin20187b2a8c32019-03-26 19:52:28 -07001045 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001046 if sn != "" {
1047 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001048 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001049 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001050 }
1051
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301052 var alarmInd oop.OnuAlarmIndication
1053 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001054 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301055
1056 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1057 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1058 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1059 OnuLosRaise event sent for it */
1060 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1061 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1062 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Shrey Baid807a2a02020-04-09 12:52:45 +05301063 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301064 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1065 "currentIntfId": onuDiscInd.GetIntfId()})
1066 // TODO:: Should we need to ignore raising OnuLosClear event
1067 // when onu connected to different PON?
1068 }
1069 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1070 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1071 alarmInd.LosStatus = statusCheckOff
1072 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1073 }
1074 return true
1075 })
1076
Girish Kumar2ad402b2020-03-20 19:45:12 +00001077 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001078 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001079 }
1080
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001081 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001082
1083 // check the ONU is already know to the OLT
1084 // NOTE the second time the ONU is discovered this should return a device
1085 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1086
1087 if err != nil {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001088 logger.Debugw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001089 if e, ok := status.FromError(err); ok {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001090 logger.Debugw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001091 switch e.Code() {
1092 case codes.Internal:
1093 // this probably means NOT FOUND, so just create a new device
1094 onuDevice = nil
1095 case codes.DeadlineExceeded:
1096 // if the call times out, cleanup and exit
1097 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001098 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001099 }
1100 }
1101 }
1102
1103 if onuDevice == nil {
1104 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001105 logger.Debugw("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001106 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001107 ponintfid := onuDiscInd.GetIntfId()
1108 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301109 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001110 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001111
Girish Kumar2ad402b2020-03-20 19:45:12 +00001112 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001113
1114 if err != nil {
1115 // if we can't create an ID in resource manager,
1116 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001117 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001118 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001119 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001120 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001121 }
1122
1123 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1124 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001125 dh.discOnus.Delete(sn)
1126 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 +05301127 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001129 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001130 }
Amit Ghosh75f0e292020-05-14 11:31:54 +01001131 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Shrey Baid807a2a02020-04-09 12:52:45 +05301132 logger.Infow("onu-child-device-added",
1133 log.Fields{"onuDevice": onuDevice,
1134 "sn": sn,
1135 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301136 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001137 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001138
1139 // we can now use the existing ONU Id
1140 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001141 //Insert the ONU into cache to use in OnuIndication.
1142 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Shrey Baid807a2a02020-04-09 12:52:45 +05301143 logger.Debugw("onu-discovery-indication-key-create",
1144 log.Fields{"onuID": onuID,
1145 "intfId": onuDiscInd.GetIntfId(),
1146 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001147 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001148
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301149 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301150 dh.onus.Store(onuKey, onuDev)
Shrey Baid807a2a02020-04-09 12:52:45 +05301151 logger.Debugw("new-onu-device-discovered",
1152 log.Fields{"onu": onuDev,
1153 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001154
David K. Bainbridge794735f2020-02-11 21:01:37 -08001155 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301156 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001158 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001159 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301160 logger.Infow("onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301162 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001164 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 }
1166 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001167}
1168
David K. Bainbridge794735f2020-02-11 21:01:37 -08001169func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001170 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1171
1172 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001173 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001174 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001175 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001176 foundInCache := false
Shrey Baid807a2a02020-04-09 12:52:45 +05301177 logger.Debugw("onu-indication-key-create",
1178 log.Fields{"onuId": onuInd.OnuId,
1179 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301180 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001181 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301182
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 errFields := log.Fields{"device-id": dh.device.Id}
1184
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301185 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1186
Mahir Gunyele77977b2019-06-27 05:36:22 -07001187 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1188 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001189 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1190 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001191 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001192 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1193 if serialNumber != "" {
1194 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001195 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001196 } else {
1197 kwargs["onu_id"] = onuInd.OnuId
1198 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001199 errFields["onu-id"] = onuInd.OnuId
1200 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001201 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001202 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001203 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001204
David K. Bainbridge794735f2020-02-11 21:01:37 -08001205 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001206 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001207 }
1208
David K. Bainbridge794735f2020-02-11 21:01:37 -08001209 if onuDevice.ParentPortNo != ponPort {
Shrey Baid807a2a02020-04-09 12:52:45 +05301210 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001211 "previousIntfId": onuDevice.ParentPortNo,
1212 "currentIntfId": ponPort})
1213 }
1214
1215 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Shrey Baid807a2a02020-04-09 12:52:45 +05301216 logger.Warnw("onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
1217 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1218 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301219 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001220 }
1221 if !foundInCache {
1222 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1223
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301224 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 -08001225
1226 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001227 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001228 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001229 }
1230 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001231}
1232
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001233func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301234 ctx := context.TODO()
Shrey Baid807a2a02020-04-09 12:52:45 +05301235 logger.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001236 if onuInd.AdminState == "down" {
Girish Gowdra429f9502020-05-04 13:22:16 -07001237 // The ONU has gone admin_state "down" and we expect the ONU to send discovery again
1238 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001239 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1240 if onuInd.OperState != "down" {
Shrey Baid807a2a02020-04-09 12:52:45 +05301241 logger.Warnw("onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001242 onuInd.OperState = "down"
1243 }
1244 }
1245
David K. Bainbridge794735f2020-02-11 21:01:37 -08001246 switch onuInd.OperState {
1247 case "down":
Shrey Baid807a2a02020-04-09 12:52:45 +05301248 logger.Debugw("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 -07001249 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301250 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001251 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1252 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301253 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001254 "onu-indicator": onuInd,
1255 "source": "openolt",
1256 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001257 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001258 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001259 case "up":
Shrey Baid807a2a02020-04-09 12:52:45 +05301260 logger.Debugw("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 -04001261 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301262 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001263 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1264 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301265 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001266 "onu-indicator": onuInd,
1267 "source": "openolt",
1268 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001269 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001270 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001271 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001272 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001273 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001275}
1276
cuilin20187b2a8c32019-03-26 19:52:28 -07001277func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1278 if serialNum != nil {
1279 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001280 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001281 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001282}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001283func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1284 decodedStr, err := hex.DecodeString(serialNum[4:])
1285 if err != nil {
1286 return nil, err
1287 }
1288 return &oop.SerialNumber{
1289 VendorId: []byte(serialNum[:4]),
1290 VendorSpecific: []byte(decodedStr),
1291 }, nil
1292}
cuilin20187b2a8c32019-03-26 19:52:28 -07001293
1294func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1295 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001296 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001297 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1298 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1299 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1300 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1301 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1302 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1303 return tmp
1304}
1305
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001306//UpdateFlowsBulk upates the bulk flow
1307func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301308 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001309}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001310
1311//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001312func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301313 logger.Debugw("getchilddevice",
1314 log.Fields{"pon-port": parentPort,
1315 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301316 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001317 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001318 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001319 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001320 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001321 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001322 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001323 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001324 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001325 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301326 logger.Debugw("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 -08001327 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301328}
1329
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001330// SendPacketInToCore sends packet-in to core
1331// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1332// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001333func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001334 logger.Debugw("send-packet-in-to-core", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301335 "port": logicalPort,
1336 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301337 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001338 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001339 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301340 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001341 "source": "adapter",
1342 "destination": "core",
1343 "device-id": dh.device.Id,
1344 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001345 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001346 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301347 logger.Debugw("sent-packet-in-to-core-successfully", log.Fields{
1348 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301349 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001350 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001351 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001352}
1353
A R Karthick1f85b802019-10-11 05:06:05 +00001354// AddUniPortToOnu adds the uni port to the onu device
1355func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1356 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301357
1358 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001359 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301360 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1361 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001362 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001363 }
1364 }
1365}
1366
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001367// UpdatePmConfig updates the pm metrics.
1368func (dh *DeviceHandler) UpdatePmConfig(pmConfigs *voltha.PmConfigs) {
1369
1370 logger.Infow("update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
1371
1372 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1373 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
1374 logger.Debugf("frequency-updated")
1375 }
1376
1377 if pmConfigs.Grouped == false {
1378 metrics := dh.metrics.GetSubscriberMetrics()
1379 for _, m := range pmConfigs.Metrics {
1380 metrics[m.Name].Enabled = m.Enabled
1381
1382 }
1383 }
1384}
1385
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001386//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301387func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301388 logger.Debugw("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 +01001389
1390 var errorsList []error
1391
Girish Gowdru0c588b22019-04-23 23:24:56 -04001392 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001393 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001394 dh.incrementActiveFlowRemoveCount(flow)
1395
Shrey Baid807a2a02020-04-09 12:52:45 +05301396 logger.Debugw("removing-flow",
1397 log.Fields{"device-id": device.Id,
1398 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001399 err := dh.flowMgr.RemoveFlow(ctx, flow)
1400 if err != nil {
1401 errorsList = append(errorsList, err)
1402 }
1403
1404 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001405 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301406
1407 for _, flow := range flows.ToAdd.Items {
Shrey Baid807a2a02020-04-09 12:52:45 +05301408 logger.Debugw("adding-flow",
1409 log.Fields{"device-id": device.Id,
1410 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001411 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1412 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001413 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1414 if err != nil {
1415 errorsList = append(errorsList, err)
1416 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301417 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001418 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001419
Girish Gowdracefae192020-03-19 18:14:10 -07001420 // 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 +00001421 if groups != nil {
1422 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001423 err := dh.flowMgr.AddGroup(ctx, group)
1424 if err != nil {
1425 errorsList = append(errorsList, err)
1426 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001427 }
1428 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001429 err := dh.flowMgr.ModifyGroup(ctx, group)
1430 if err != nil {
1431 errorsList = append(errorsList, err)
1432 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001433 }
1434 if len(groups.ToRemove.Items) != 0 {
Thomas Lee S985938d2020-05-04 11:40:41 +05301435 logger.Debugw("group-delete-operation-not-supported", log.Fields{"device-id": dh.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001436 }
1437 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001438 if len(errorsList) > 0 {
1439 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1440 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301441 logger.Debugw("updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001442 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301443}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001444
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445//DisableDevice disables the given device
1446//It marks the following for the given device:
1447//Device-Handler Admin-State : down
1448//Device Port-State: UNKNOWN
1449//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001450func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001451 /* On device disable ,admin state update has to be done prior sending request to agent since
1452 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001453 if dh.Client != nil {
1454 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1455 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001456 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001457 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001458 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001459 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301460 logger.Debugw("olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001461 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001462 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301463
1464 dh.discOnus = sync.Map{}
1465 dh.onus = sync.Map{}
1466
Thomas Lee S85f37312020-04-03 17:06:12 +05301467 //stopping the stats collector
1468 dh.stopCollector <- true
1469
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301470 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001471 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301472 //Update device Admin state
1473 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001474 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1475 for _, port := range cloned.Ports {
1476 if port.GetType() == voltha.Port_PON_OLT {
1477 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1478 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001479 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001480 }
1481 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001482 }
1483
Shrey Baid807a2a02020-04-09 12:52:45 +05301484 logger.Debugw("disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001485 return nil
1486}
1487
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301488func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001489
1490 // Update onu state as unreachable in onu adapter
1491 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301492 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001493 //get the child device for the parent device
1494 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1495 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301496 logger.Errorw("failed-to-get-child-devices-information", log.Fields{"device-id": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001497 }
1498 if onuDevices != nil {
1499 for _, onuDevice := range onuDevices.Items {
1500 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1501 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1502 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001503 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301504 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001505 }
1506
1507 }
1508 }
1509
1510}
1511
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001512//ReenableDevice re-enables the olt device after disable
1513//It marks the following for the given device:
1514//Device-Handler Admin-State : up
1515//Device Port-State: ACTIVE
1516//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001517func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301518
1519 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1520 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001521 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301522 }
1523 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001524 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001525
1526 cloned := proto.Clone(device).(*voltha.Device)
1527 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001528
kdarapu1afeceb2020-02-12 01:38:09 -05001529 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001530 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001531 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001532 //Update the device oper status as ACTIVE
1533 cloned.OperStatus = voltha.OperStatus_ACTIVE
1534 dh.device = cloned
1535
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001536 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301537 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001538 "device-id": device.Id,
1539 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001540 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001541 }
kesavand39e0aa32020-01-28 20:58:50 -05001542
Shrey Baid807a2a02020-04-09 12:52:45 +05301543 logger.Debugw("reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001544
1545 return nil
1546}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001547
npujarec5762e2020-01-01 14:08:48 +05301548func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001549 var uniID uint32
1550 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301551 for _, port := range onu.UniPorts {
1552 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001553 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001554 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301555 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301556 logger.Debugw("failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001557 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301558 logger.Debugw("deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301559 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001560 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301561 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001562 }
npujarec5762e2020-01-01 14:08:48 +05301563 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001564 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301565 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301566 logger.Debugw("failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001567 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301568 logger.Debugw("removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301569 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301570 logger.Debugw("failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001571 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301572 logger.Debugw("removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301573 }
npujarec5762e2020-01-01 14:08:48 +05301574 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1575 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301576 logger.Debugw("failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301577 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301578 logger.Debugw("removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301579 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301580 logger.Debugw("failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001581 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001582 }
1583 return nil
1584}
1585
npujarec5762e2020-01-01 14:08:48 +05301586func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001587 nniUniID := -1
1588 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301589
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001590 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301591 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001592 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001593 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301594 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301595 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001596 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001597 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301598 logger.Debugw("nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301599 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301600 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Shrey Baid807a2a02020-04-09 12:52:45 +05301601 logger.Debugw("current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301602 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301603 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301604 }
npujarec5762e2020-01-01 14:08:48 +05301605 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001606 }
npujarec5762e2020-01-01 14:08:48 +05301607 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001608 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301609 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001611}
1612
1613// 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 +05301614func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301615 logger.Debug("function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001616 /* Clear the KV store data associated with the all the UNI ports
1617 This clears up flow data and also resource map data for various
1618 other pon resources like alloc_id and gemport_id
1619 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001620 go dh.cleanupDeviceResources(ctx)
Shrey Baid807a2a02020-04-09 12:52:45 +05301621 logger.Debug("removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001622 // Stop the Stats collector
1623 dh.stopCollector <- true
1624 // stop the heartbeat check routine
1625 dh.stopHeartbeatCheck <- true
1626 //Reset the state
1627 if dh.Client != nil {
1628 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301629 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001630 }
1631 }
1632 cloned := proto.Clone(device).(*voltha.Device)
1633 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1634 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1635 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1636 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1637 "device-id": device.Id,
1638 "connect-status": cloned.ConnectStatus,
1639 "oper-status": cloned.OperStatus}, err).Log()
1640 }
1641 return nil
1642}
1643func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001644 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301645 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1646 var ponPort uint32
1647 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1648 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301649 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301650 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301651 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001652 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001653 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301654 }
1655 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301656 onuID := make([]uint32, 1)
Shrey Baid807a2a02020-04-09 12:52:45 +05301657 logger.Debugw("onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301658 if err = dh.clearUNIData(ctx, &onu); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301659 logger.Errorw("failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301660 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301661 // Clear flowids for gem cache.
1662 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301663 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301664 }
1665 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301666 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301667 }
npujarec5762e2020-01-01 14:08:48 +05301668 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301669 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301670 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301671 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301672 logger.Errorw("failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001673 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001674 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001675 /* Clear the flows from KV store associated with NNI port.
1676 There are mostly trap rules from NNI port (like LLDP)
1677 */
npujarec5762e2020-01-01 14:08:48 +05301678 if err := dh.clearNNIData(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301679 logger.Errorw("failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001680 }
A R Karthick1f85b802019-10-11 05:06:05 +00001681
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001682 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301683 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001684 }
A R Karthick1f85b802019-10-11 05:06:05 +00001685
Devmalya Paul495b94a2019-08-27 19:42:00 -04001686 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301687 dh.onus.Range(func(key interface{}, value interface{}) bool {
1688 dh.onus.Delete(key)
1689 return true
1690 })
1691
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001692 /*Delete discovered ONU map for the device*/
1693 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1694 dh.discOnus.Delete(key)
1695 return true
1696 })
1697
Devmalya Paul495b94a2019-08-27 19:42:00 -04001698 return nil
1699}
1700
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001701//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001702func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1703 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301704 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001705 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301706 logger.Debugw("rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001707 return nil
1708}
1709
David K. Bainbridge794735f2020-02-11 21:01:37 -08001710func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301711 logger.Debugw("received-packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001712 "packet-indication": *packetIn,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001713 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001714 "packet": hex.EncodeToString(packetIn.Pkt),
1715 })
npujarec5762e2020-01-01 14:08:48 +05301716 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001717 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001718 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001719 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301720 logger.Debugw("sending-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001721 "logicalPortNum": logicalPortNum,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001722 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001723 "packet": hex.EncodeToString(packetIn.Pkt),
1724 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001725 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301726 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001727 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301728 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001729 "device-id": dh.device.Id,
1730 "packet": hex.EncodeToString(packetIn.Pkt),
1731 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001732 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301733 logger.Debugw("success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001734 "packet": hex.EncodeToString(packetIn.Pkt),
Thomas Lee S985938d2020-05-04 11:40:41 +05301735 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001736 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001737 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001738}
1739
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001740// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301741func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001742 logger.Debugw("incoming-packet-out", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301743 "device-id": dh.device.Id,
Shrey Baid807a2a02020-04-09 12:52:45 +05301744 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001745 "pkt-length": len(packet.Data),
1746 "packet": hex.EncodeToString(packet.Data),
1747 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001748
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001749 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001750 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001751 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1752 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301753 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1754 // Do not packet-out lldp packets on uni port.
1755 // ONOS has no clue about uni/nni ports, it just packets out on all
1756 // available ports on the Logical Switch. It should not be interested
1757 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001758 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1759 "device-id": dh.device.Id,
1760 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301761 return nil
1762 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001763 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1764 if innerEthType == 0x8100 {
1765 // q-in-q 802.1ad or 802.1q double tagged packet.
1766 // slice out the outer tag.
1767 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001768 logger.Debugw("packet-now-single-tagged", log.Fields{
1769 "packetData": hex.EncodeToString(packet.Data),
1770 "device-id": dh.device.Id,
1771 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001772 }
1773 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001774 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1775 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001776 uniID := UniIDFromPortNum(uint32(egressPortNo))
1777
npujarec5762e2020-01-01 14:08:48 +05301778 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001779 if err != nil {
1780 // In this case the openolt agent will receive the gemPortID as 0.
1781 // The agent tries to retrieve the gemPortID in this case.
1782 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001783 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001784 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301785 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001786 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001787 }
1788
1789 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001790
Girish Kumar2ad402b2020-03-20 19:45:12 +00001791 logger.Debugw("sending-packet-to-onu", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301792 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001793 "IntfId": intfID,
1794 "onuID": onuID,
1795 "uniID": uniID,
1796 "gemPortID": gemPortID,
1797 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301798 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001799 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001800
npujarec5762e2020-01-01 14:08:48 +05301801 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301802 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001803 "source": "adapter",
1804 "destination": "onu",
1805 "egress-port-number": egressPortNo,
1806 "interface-id": intfID,
1807 "oni-id": onuID,
1808 "uni-id": uniID,
1809 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001810 "packet": hex.EncodeToString(packet.Data),
1811 "device-id": dh.device.Id,
1812 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001813 }
1814 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001815 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1816 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001817 return olterrors.NewErrInvalidValue(log.Fields{
1818 "egress-nni-port": egressPortNo,
1819 "device-id": dh.device.Id,
1820 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001821 }
1822 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001823
Girish Kumar2ad402b2020-03-20 19:45:12 +00001824 logger.Debugw("sending-packet-to-nni", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301825 "uplink-pkt": uplinkPkt,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001826 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301827 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001828 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001829
npujarec5762e2020-01-01 14:08:48 +05301830 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001831 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1832 "packet": hex.EncodeToString(packet.Data),
1833 "device-id": dh.device.Id,
1834 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001835 }
1836 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301837 logger.Warnw("packet-out-to-this-interface-type-not-implemented", log.Fields{
1838 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001839 "egressPortType": egressPortType,
1840 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301841 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001842 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001843 }
1844 return nil
1845}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001846
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001847func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1848 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001849}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301850
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001851func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301852 // start the heartbeat check towards the OLT.
1853 var timerCheck *time.Timer
1854
1855 for {
1856 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1857 select {
1858 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001859 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1860 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301861 logger.Warnw("hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301862 if timerCheck == nil {
1863 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001864 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301865 }
1866 } else {
1867 if timerCheck != nil {
1868 if timerCheck.Stop() {
Thomas Lee S985938d2020-05-04 11:40:41 +05301869 logger.Debugw("got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301870 }
1871 timerCheck = nil
1872 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301873 logger.Debugw("hearbeat",
1874 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301875 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301876 }
1877 cancel()
1878 case <-dh.stopHeartbeatCheck:
Thomas Lee S985938d2020-05-04 11:40:41 +05301879 logger.Debugw("stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301880 return
1881 }
1882 }
1883}
1884
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001885func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1886 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1887 if err != nil || device == nil {
1888 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1889 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301890
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001891 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1892 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1893 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1894 }
1895 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1896 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1897 }
1898 go dh.cleanupDeviceResources(ctx)
1899
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001900 dh.lockDevice.RLock()
1901 // Stop the read indication only if it the routine is active
1902 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1903 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1904 // on next execution of the readIndication routine.
1905 if dh.isReadIndicationRoutineActive {
1906 dh.stopIndications <- true
1907 }
1908 dh.lockDevice.RUnlock()
1909
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001910 dh.transitionMap.Handle(ctx, DeviceInit)
1911
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301912 }
1913}
kesavand39e0aa32020-01-28 20:58:50 -05001914
1915// EnablePort to enable Pon interface
1916func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001917 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001918 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001919}
1920
1921// DisablePort to disable pon interface
1922func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001923 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001924 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001925}
1926
kdarapu1afeceb2020-02-12 01:38:09 -05001927//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1928func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301929 ctx := context.Background()
Thomas Lee S985938d2020-05-04 11:40:41 +05301930 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05001931 if port.GetType() == voltha.Port_ETHERNET_NNI {
1932 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001933 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301934 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301935 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001936 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001937 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001938 }
1939 // fetch interfaceid from PortNo
1940 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1941 ponIntf := &oop.Interface{IntfId: ponID}
1942 var operStatus voltha.OperStatus_Types
1943 if enablePort {
1944 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301945 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001946
1947 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301948 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001949 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001950 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001951 }
1952 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001953 dh.activePorts.Store(ponID, true)
Shrey Baid807a2a02020-04-09 12:52:45 +05301954 logger.Infow("enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001955 } else {
1956 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301957 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001958 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301959 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001960 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001961 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001962 }
1963 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001964 dh.activePorts.Store(ponID, false)
Shrey Baid807a2a02020-04-09 12:52:45 +05301965 logger.Infow("disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001966 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301967 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 +05301968 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301969 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001970 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001971 }
1972 return nil
1973}
1974
kdarapu1afeceb2020-02-12 01:38:09 -05001975//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1976func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001977 cloned := proto.Clone(device).(*voltha.Device)
1978 // Disable the port and update the oper_port_status to core
1979 // if the Admin state of the port is disabled on reboot and re-enable device.
1980 for _, port := range cloned.Ports {
1981 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001982 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301983 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301984 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001985 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001986 }
1987 }
1988 }
1989 return nil
1990}
1991
1992//populateActivePorts to populate activePorts map
1993func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301994 logger.Infow("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001995 for _, port := range device.Ports {
1996 if port.Type == voltha.Port_ETHERNET_NNI {
1997 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001998 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001999 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002000 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002001 }
2002 }
2003 if port.Type == voltha.Port_PON_OLT {
2004 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002005 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002006 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002007 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002008 }
2009 }
2010 }
2011}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002012
2013// ChildDeviceLost deletes ONU and clears pon resources related to it.
2014func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002015 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002016 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2017 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002018 onuDevice, ok := dh.onus.Load(onuKey)
2019 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302020 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002021 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302022 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002023 "onu-id": onuID,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002024 "interface-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002025 }
2026 var sn *oop.SerialNumber
2027 var err error
2028 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302029 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002030 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302031 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002032 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2033 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002034
2035 for uniID := 0; uniID < MaxUnisPerOnu; uniID++ {
2036 var flowRemoveData pendingFlowRemoveData
2037 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uint32(uniID)}
2038 dh.lockDevice.RLock()
2039 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2040 dh.lockDevice.RUnlock()
2041 continue
2042 }
2043 dh.lockDevice.RUnlock()
2044
2045 log.Debugw("wait-for-flow-remove-complete-before-processing-child-device-lost",
2046 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2047 // Wait for all flow removes to finish first
2048 <-flowRemoveData.allFlowsRemoved
2049 log.Debugw("flow-removes-complete-for-subscriber",
2050 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2051 }
2052
2053 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002054 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302055 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302056 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002057 "onu-id": onuID}, err).Log()
2058 }
2059 //clear PON resources associated with ONU
2060 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002061 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002062 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302063 "device-id": dh.device.Id,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002064 "interface-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002065 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002066 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05302067 logger.Warnw("failed-to-get-onu-info-for-pon-port", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302068 "device-id": dh.device.Id,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002069 "interface-id": intfID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002070 "error": err})
2071 } else {
2072 for i, onu := range onuGemData {
2073 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Shrey Baid807a2a02020-04-09 12:52:45 +05302074 logger.Debugw("onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002075 if err := dh.clearUNIData(ctx, &onu); err != nil {
2076 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302077 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002078 "onu-device": onu,
2079 "error": err})
2080 }
2081 // Clear flowids for gem cache.
2082 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002083 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002084 }
2085 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002086 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002087 if err != nil {
2088 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002089 "interface-id": intfID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002090 "onu-device": onu,
2091 "onu-gem": onuGemData,
2092 "error": err})
2093 //Not returning error on cleanup.
2094 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002095 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
2096 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002097 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002098 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002099 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002100 }
2101 }
2102 dh.onus.Delete(onuKey)
2103 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2104 return nil
2105}
Girish Gowdracefae192020-03-19 18:14:10 -07002106
2107func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2108 for _, field := range flows.GetOfbFields(flow) {
2109 if field.Type == flows.IN_PORT {
2110 return field.GetPort()
2111 }
2112 }
2113 return InvalidPort
2114}
2115
2116func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2117 for _, action := range flows.GetActions(flow) {
2118 if action.Type == flows.OUTPUT {
2119 if out := action.GetOutput(); out != nil {
2120 return out.GetPort()
2121 }
2122 }
2123 }
2124 return InvalidPort
2125}
2126
2127func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2128 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302129 logger.Debugw("increment-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002130 if inPort != InvalidPort && outPort != InvalidPort {
2131 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2132 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302133 logger.Debugw("increment-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002134
2135 dh.lockDevice.Lock()
2136 defer dh.lockDevice.Unlock()
2137 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2138 if !ok {
2139 flowRemoveData = pendingFlowRemoveData{
2140 pendingFlowRemoveCount: 0,
2141 allFlowsRemoved: make(chan struct{}),
2142 }
2143 }
2144 flowRemoveData.pendingFlowRemoveCount++
2145 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2146
Shrey Baid807a2a02020-04-09 12:52:45 +05302147 logger.Debugw("current-flow-remove-count–increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002148 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2149 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2150 }
2151}
2152
2153func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2154 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302155 logger.Debugw("decrement-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002156 if inPort != InvalidPort && outPort != InvalidPort {
2157 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2158 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302159 logger.Debugw("decrement-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002160
2161 dh.lockDevice.Lock()
2162 defer dh.lockDevice.Unlock()
2163 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302164 logger.Fatalf("flow-remove-key-not-found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002165 } else {
2166 if val.pendingFlowRemoveCount > 0 {
2167 val.pendingFlowRemoveCount--
2168 }
Shrey Baid807a2a02020-04-09 12:52:45 +05302169 logger.Debugw("current-flow-remove-count-after-decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002170 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2171 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2172 // If all flow removes have finished, then close the channel to signal the receiver
2173 // to go ahead with flow adds.
2174 if val.pendingFlowRemoveCount == 0 {
2175 close(val.allFlowsRemoved)
2176 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2177 return
2178 }
2179 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2180 }
2181 }
2182}
2183
2184func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2185 var flowRemoveData pendingFlowRemoveData
2186 var ok bool
2187 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302188 logger.Debugw("wait-for-flow-remove-to-finish-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002189 if inPort != InvalidPort && outPort != InvalidPort {
2190 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2191 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302192 logger.Debugw("wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002193
2194 dh.lockDevice.RLock()
2195 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302196 logger.Debugw("no-pending-flow-to-remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002197 dh.lockDevice.RUnlock()
2198 return
2199 }
2200 dh.lockDevice.RUnlock()
2201
2202 // Wait for all flow removes to finish first
2203 <-flowRemoveData.allFlowsRemoved
2204
Shrey Baid807a2a02020-04-09 12:52:45 +05302205 logger.Debugw("all-flows-cleared--handling-flow-add-now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002206 }
2207}
2208
2209func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2210 inPort := getInPortFromFlow(flow)
2211 outPort := getOutPortFromFlow(flow)
2212
2213 if inPort == InvalidPort || outPort == InvalidPort {
2214 return inPort, outPort
2215 }
2216
2217 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2218 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2219 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2220 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2221 return uniPort, outPort
2222 }
2223 }
2224 } else {
2225 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2226 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2227 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2228 return inPort, uniPort
2229 }
2230 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2231 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2232 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2233 return uniPort, outPort
2234 }
2235 }
2236 }
2237
2238 return InvalidPort, InvalidPort
2239}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002240
2241func extractOmciTransactionID(omciPkt []byte) uint16 {
2242 if len(omciPkt) > 3 {
2243 d := omciPkt[0:2]
2244 transid := binary.BigEndian.Uint16(d)
2245 return transid
2246 }
2247 return 0
2248}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002249
2250// StoreOnuDevice stores the onu parameters to the local cache.
2251func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2252 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2253 dh.onus.Store(onuKey, onuDevice)
2254}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002255
Devmalya Paula1efa642020-04-20 01:36:43 -04002256// setOnuITUPonAlarmConfig sets the parameters in the openolt agent for raising the ONU ITU PON alarms.
2257func (dh *DeviceHandler) setOnuITUPonAlarmConfig(config *oop.OnuItuPonAlarm) error {
2258 if _, err := dh.Client.OnuItuPonAlarmSet(context.Background(), config); err != nil {
2259 return err
2260 }
2261 logger.Debugw("onu-itu-pon-alarm-config-set-successful", log.Fields{"config": config})
2262 return nil
2263}
2264
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002265func (dh *DeviceHandler) getExtValue(device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
2266 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002267 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002268 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002269 resp := new(voltha.ReturnValues)
2270 valueparam := new(oop.ValueParam)
2271 ctx := context.Background()
2272 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002273 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2274 return nil, err
2275 }
2276 ID = device.ProxyAddress.GetOnuId()
2277 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2278 valueparam.Onu = &Onu
2279 valueparam.Value = value
2280
2281 // This API is unsupported until agent patch is added
2282 resp.Unsupported = uint32(value)
2283 _ = ctx
2284
2285 // Uncomment this code once agent changes are complete and tests
2286 /*
2287 resp, err = dh.Client.GetValue(ctx, valueparam)
2288 if err != nil {
2289 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2290 return nil, err
2291 }
2292 */
2293
2294 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2295 return resp, nil
2296}