blob: 212e096717e1fedc151e546e1a69eabaaa036f40 [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()
cuilin20187b2a8c32019-03-26 19:52:28 -0700706 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530707}
708
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400709func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
710 deviceInfo, err := dh.populateDeviceInfo()
711
712 if err != nil {
713 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
714 }
715 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
716 // Instantiate resource manager
Thomas Lee S985938d2020-05-04 11:40:41 +0530717 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.device.Id, KVStoreHostPort, dh.openOLT.KVStoreType, dh.device.Type, deviceInfo); dh.resourceMgr == nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400718 return olterrors.ErrResourceManagerInstantiating
719 }
720
721 // Instantiate flow manager
722 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
723 return olterrors.ErrResourceManagerInstantiating
724
725 }
726 /* TODO: Instantiate Alarm , stats , BW managers */
727 /* Instantiating Event Manager to handle Alarms and KPIs */
728 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
729
730 // Stats config for new device
731 dh.portStats = NewOpenOltStatsMgr(dh)
732
733 return nil
734
735}
736
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400737func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
738 var err error
739 var deviceInfo *oop.DeviceInfo
740
741 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
742
743 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000744 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400745 }
746 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000747 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400748 }
749
Thomas Lee S985938d2020-05-04 11:40:41 +0530750 logger.Debugw("fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400751 dh.device.Root = true
752 dh.device.Vendor = deviceInfo.Vendor
753 dh.device.Model = deviceInfo.Model
754 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
755 dh.device.HardwareVersion = deviceInfo.HardwareVersion
756 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
757
758 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000759 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400760 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
761 genmac, err := generateMacFromHost(host)
762 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000763 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400764 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000765 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400766 dh.device.MacAddress = genmac
767 } else {
768 dh.device.MacAddress = deviceInfo.DeviceId
769 }
770
771 // Synchronous call to update device - this method is run in its own go routine
772 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000773 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400774 }
775
776 return deviceInfo, nil
777}
778
Naga Manjunath7615e552019-10-11 22:35:47 +0530779func startCollector(dh *DeviceHandler) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530780 logger.Debugf("starting-collector")
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530781 freq := dh.metrics.ToPmConfigs().DefaultFreq
Naga Manjunath7615e552019-10-11 22:35:47 +0530782 for {
783 select {
784 case <-dh.stopCollector:
Thomas Lee S985938d2020-05-04 11:40:41 +0530785 logger.Debugw("stopping-collector-for-olt", log.Fields{"deviceID:": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530786 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530787 case <-time.After(time.Duration(freq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700788
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530789 ports := make([]*voltha.Port, len(dh.device.Ports))
790 copy(ports, dh.device.Ports)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530791 for _, port := range ports {
792 // NNI Stats
793 if port.Type == voltha.Port_ETHERNET_NNI {
794 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
795 cmnni := dh.portStats.collectNNIMetrics(intfID)
796 logger.Debugw("collect-nni-metrics", log.Fields{"metrics": cmnni})
Girish Gowdra34815db2020-05-11 17:18:04 -0700797 go dh.portStats.publishMetrics(cmnni, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530798 logger.Debugw("publish-nni-metrics", log.Fields{"nni-port": port.Label})
799 }
800 // PON Stats
801 if port.Type == voltha.Port_PON_OLT {
802 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
803 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
804 cmpon := dh.portStats.collectPONMetrics(intfID)
805 logger.Debugw("collect-pon-metrics", log.Fields{"metrics": cmpon})
Girish Gowdra34815db2020-05-11 17:18:04 -0700806 go dh.portStats.publishMetrics(cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530807 }
808 logger.Debugw("publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500809 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530810 }
811 }
812 }
813}
814
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700815//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530816func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400817 dh.transitionMap = NewTransitionMap(dh)
Shrey Baid807a2a02020-04-09 12:52:45 +0530818 logger.Infow("adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530819 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530820
821 // Now, set the initial PM configuration for that device
822 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530823 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530824 }
825
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400826 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530827}
828
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700829//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530830func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700831 return &ic.SwitchCapability{
832 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530833 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700834 HwDesc: "open_pon",
835 SwDesc: "open_pon",
836 SerialNum: dh.device.SerialNumber,
837 },
838 SwitchFeatures: &of.OfpSwitchFeatures{
839 NBuffers: 256,
840 NTables: 2,
841 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
842 of.OfpCapabilities_OFPC_TABLE_STATS |
843 of.OfpCapabilities_OFPC_PORT_STATS |
844 of.OfpCapabilities_OFPC_GROUP_STATS),
845 },
846 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530847}
848
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700849//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530850func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700851 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700852 return &ic.PortCapability{
853 Port: &voltha.LogicalPort{
854 OfpPort: &of.OfpPort{
855 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
856 Config: 0,
857 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700858 Curr: capacity,
859 Advertised: capacity,
860 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700861 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
862 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
863 },
864 DeviceId: dh.device.Id,
865 DevicePortNo: uint32(portNo),
866 },
867 }, nil
868}
869
David K. Bainbridge794735f2020-02-11 21:01:37 -0800870func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530871 logger.Debugw("omci-indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700872 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700873 var deviceID string
874 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700875
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400876 transid := extractOmciTransactionID(omciInd.Pkt)
Thomas Lee S985938d2020-05-04 11:40:41 +0530877 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 -0400878 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
879
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700880 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530881
882 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
883
Thomas Lee S985938d2020-05-04 11:40:41 +0530884 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 -0700885 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700886 kwargs := make(map[string]interface{})
887 kwargs["onu_id"] = omciInd.OnuId
888 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700889
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700890 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
891 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530892 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800893 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000894 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700895 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700896 deviceType = onuDevice.Type
897 deviceID = onuDevice.Id
898 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
899 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530900 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700901 } else {
902 //found in cache
Thomas Lee S985938d2020-05-04 11:40:41 +0530903 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 +0530904 deviceType = onuInCache.(*OnuDevice).deviceType
905 deviceID = onuInCache.(*OnuDevice).deviceID
906 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700907 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700908
909 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800910 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Thomas Lee S985938d2020-05-04 11:40:41 +0530911 ic.InterAdapterMessageType_OMCI_REQUEST, dh.device.Type, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800912 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530913 return olterrors.NewErrCommunication("omci-request", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530914 "source": dh.device.Type,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800915 "destination": deviceType,
916 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000917 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700918 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800919 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530920}
921
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700922//ProcessInterAdapterMessage sends the proxied messages to the target device
923// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
924// is meant, and then send the unmarshalled omci message to this onu
925func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530926 logger.Debugw("process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700927 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700928 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700929 fromTopic := msg.Header.FromTopic
930 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700931 toDeviceID := msg.Header.ToDeviceId
932 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700933
Shrey Baid807a2a02020-04-09 12:52:45 +0530934 logger.Debugw("omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700935
936 msgBody := msg.GetBody()
937
938 omciMsg := &ic.InterAdapterOmciMessage{}
939 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000940 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700941 }
942
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700943 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700944 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
945 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530946 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800947 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000948 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700949 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530950 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 -0800951 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530952 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800953 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000954 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800955 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700956 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +0530957 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 -0800958 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530959 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800960 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000961 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800962 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700963 }
964
965 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000966 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700967 }
968 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530969}
970
David K. Bainbridge794735f2020-02-11 21:01:37 -0800971func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700972 var intfID uint32
973 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000974 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700975 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976 intfID = onuDevice.ProxyAddress.GetChannelId()
977 onuID = onuDevice.ProxyAddress.GetOnuId()
978 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700979 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700980 intfID = omciMsg.GetProxyAddress().GetChannelId()
981 onuID = omciMsg.GetProxyAddress().GetOnuId()
982 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700983 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700984 if connectStatus != voltha.ConnectStatus_REACHABLE {
Shrey Baid807a2a02020-04-09 12:52:45 +0530985 logger.Debugw("onu-not-reachable--cannot-send-omci", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800986
Thomas Lee S94109f12020-03-03 16:39:29 +0530987 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800988 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000989 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700990 }
991
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400992 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
993 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700994 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400995 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
996 hex.Encode(hexPkt, omciMsg.Message)
997 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
998
999 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1000 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1001 transid := extractOmciTransactionID(omciMsg.Message)
1002 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
1003 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001004
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
1006 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301007 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001008 "interface-id": intfID,
1009 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001010 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001011 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001012 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001013}
1014
David K. Bainbridge794735f2020-02-11 21:01:37 -08001015func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301016 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 +02001017 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
1018 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
1019 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001020 // TODO: need resource manager
1021 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001022 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301023 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001024 st, _ := status.FromError(err)
1025 if st.Code() == codes.AlreadyExists {
Thomas Lee S985938d2020-05-04 11:40:41 +05301026 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 -04001027 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301028 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001029 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001030 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301031 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001032 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001033 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001034}
1035
David K. Bainbridge794735f2020-02-11 21:01:37 -08001036func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001037
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001038 channelID := onuDiscInd.GetIntfId()
1039 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001040
Girish Kumar2ad402b2020-03-20 19:45:12 +00001041 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301042
cuilin20187b2a8c32019-03-26 19:52:28 -07001043 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001044 if sn != "" {
1045 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001046 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001047 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001048 }
1049
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301050 var alarmInd oop.OnuAlarmIndication
1051 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001052 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301053
1054 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1055 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1056 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1057 OnuLosRaise event sent for it */
1058 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1059 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1060 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Shrey Baid807a2a02020-04-09 12:52:45 +05301061 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301062 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1063 "currentIntfId": onuDiscInd.GetIntfId()})
1064 // TODO:: Should we need to ignore raising OnuLosClear event
1065 // when onu connected to different PON?
1066 }
1067 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1068 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1069 alarmInd.LosStatus = statusCheckOff
1070 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1071 }
1072 return true
1073 })
1074
Girish Kumar2ad402b2020-03-20 19:45:12 +00001075 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001076 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001077 }
1078
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001079 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001080
1081 // check the ONU is already know to the OLT
1082 // NOTE the second time the ONU is discovered this should return a device
1083 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1084
1085 if err != nil {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001086 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 -08001087 if e, ok := status.FromError(err); ok {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001088 logger.Debugw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001089 switch e.Code() {
1090 case codes.Internal:
1091 // this probably means NOT FOUND, so just create a new device
1092 onuDevice = nil
1093 case codes.DeadlineExceeded:
1094 // if the call times out, cleanup and exit
1095 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001096 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001097 }
1098 }
1099 }
1100
1101 if onuDevice == nil {
1102 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001103 logger.Debugw("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001104 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001105 ponintfid := onuDiscInd.GetIntfId()
1106 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301107 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001108 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001109
Girish Kumar2ad402b2020-03-20 19:45:12 +00001110 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001111
1112 if err != nil {
1113 // if we can't create an ID in resource manager,
1114 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001115 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001116 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001117 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001118 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001119 }
1120
1121 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1122 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001123 dh.discOnus.Delete(sn)
1124 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 +05301125 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001127 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001128 }
Amit Ghosh75f0e292020-05-14 11:31:54 +01001129 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Shrey Baid807a2a02020-04-09 12:52:45 +05301130 logger.Infow("onu-child-device-added",
1131 log.Fields{"onuDevice": onuDevice,
1132 "sn": sn,
1133 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301134 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001135 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001136
1137 // we can now use the existing ONU Id
1138 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001139 //Insert the ONU into cache to use in OnuIndication.
1140 //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 +05301141 logger.Debugw("onu-discovery-indication-key-create",
1142 log.Fields{"onuID": onuID,
1143 "intfId": onuDiscInd.GetIntfId(),
1144 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001145 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001146
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301147 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301148 dh.onus.Store(onuKey, onuDev)
Shrey Baid807a2a02020-04-09 12:52:45 +05301149 logger.Debugw("new-onu-device-discovered",
1150 log.Fields{"onu": onuDev,
1151 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001152
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301154 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001155 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001156 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001157 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301158 logger.Infow("onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301160 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001162 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 }
1164 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001165}
1166
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001168 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1169
1170 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001171 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001172 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001174 foundInCache := false
Shrey Baid807a2a02020-04-09 12:52:45 +05301175 logger.Debugw("onu-indication-key-create",
1176 log.Fields{"onuId": onuInd.OnuId,
1177 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301178 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001179 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301180
David K. Bainbridge794735f2020-02-11 21:01:37 -08001181 errFields := log.Fields{"device-id": dh.device.Id}
1182
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301183 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1184
Mahir Gunyele77977b2019-06-27 05:36:22 -07001185 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1186 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001187 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1188 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001189 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001190 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1191 if serialNumber != "" {
1192 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001194 } else {
1195 kwargs["onu_id"] = onuInd.OnuId
1196 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 errFields["onu-id"] = onuInd.OnuId
1198 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001199 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001201 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001202
David K. Bainbridge794735f2020-02-11 21:01:37 -08001203 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001204 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001205 }
1206
David K. Bainbridge794735f2020-02-11 21:01:37 -08001207 if onuDevice.ParentPortNo != ponPort {
Shrey Baid807a2a02020-04-09 12:52:45 +05301208 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001209 "previousIntfId": onuDevice.ParentPortNo,
1210 "currentIntfId": ponPort})
1211 }
1212
1213 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Shrey Baid807a2a02020-04-09 12:52:45 +05301214 logger.Warnw("onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
1215 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1216 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301217 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 }
1219 if !foundInCache {
1220 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1221
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301222 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 -08001223
1224 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001225 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001226 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001227 }
1228 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001229}
1230
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001231func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301232 ctx := context.TODO()
Shrey Baid807a2a02020-04-09 12:52:45 +05301233 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 +00001234 if onuInd.AdminState == "down" {
Girish Gowdra429f9502020-05-04 13:22:16 -07001235 // The ONU has gone admin_state "down" and we expect the ONU to send discovery again
1236 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001237 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1238 if onuInd.OperState != "down" {
Shrey Baid807a2a02020-04-09 12:52:45 +05301239 logger.Warnw("onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001240 onuInd.OperState = "down"
1241 }
1242 }
1243
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 switch onuInd.OperState {
1245 case "down":
Shrey Baid807a2a02020-04-09 12:52:45 +05301246 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 -07001247 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301248 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001249 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1250 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301251 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 "onu-indicator": onuInd,
1253 "source": "openolt",
1254 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001255 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001256 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001257 case "up":
Shrey Baid807a2a02020-04-09 12:52:45 +05301258 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 -04001259 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301260 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001261 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1262 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301263 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264 "onu-indicator": onuInd,
1265 "source": "openolt",
1266 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001267 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001268 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001269 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001270 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001271 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001273}
1274
cuilin20187b2a8c32019-03-26 19:52:28 -07001275func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1276 if serialNum != nil {
1277 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001278 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001279 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001280}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001281func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1282 decodedStr, err := hex.DecodeString(serialNum[4:])
1283 if err != nil {
1284 return nil, err
1285 }
1286 return &oop.SerialNumber{
1287 VendorId: []byte(serialNum[:4]),
1288 VendorSpecific: []byte(decodedStr),
1289 }, nil
1290}
cuilin20187b2a8c32019-03-26 19:52:28 -07001291
1292func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1293 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001294 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001295 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1296 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1297 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1298 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1299 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1300 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1301 return tmp
1302}
1303
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001304//UpdateFlowsBulk upates the bulk flow
1305func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301306 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001307}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001308
1309//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301311 logger.Debugw("getchilddevice",
1312 log.Fields{"pon-port": parentPort,
1313 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301314 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001315 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001316 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001317 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001318 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001319 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001320 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001321 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001322 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001323 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301324 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 -08001325 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301326}
1327
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001328// SendPacketInToCore sends packet-in to core
1329// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1330// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001331func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001332 logger.Debugw("send-packet-in-to-core", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301333 "port": logicalPort,
1334 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301335 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001336 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001337 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301338 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001339 "source": "adapter",
1340 "destination": "core",
1341 "device-id": dh.device.Id,
1342 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001343 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001344 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301345 logger.Debugw("sent-packet-in-to-core-successfully", log.Fields{
1346 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301347 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001348 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001350}
1351
A R Karthick1f85b802019-10-11 05:06:05 +00001352// AddUniPortToOnu adds the uni port to the onu device
1353func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1354 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301355
1356 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001357 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301358 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1359 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001360 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001361 }
1362 }
1363}
1364
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001365//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301366func (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 +05301367 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 +01001368
1369 var errorsList []error
1370
Girish Gowdru0c588b22019-04-23 23:24:56 -04001371 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001372 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001373 dh.incrementActiveFlowRemoveCount(flow)
1374
Shrey Baid807a2a02020-04-09 12:52:45 +05301375 logger.Debugw("removing-flow",
1376 log.Fields{"device-id": device.Id,
1377 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001378 err := dh.flowMgr.RemoveFlow(ctx, flow)
1379 if err != nil {
1380 errorsList = append(errorsList, err)
1381 }
1382
1383 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001384 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301385
1386 for _, flow := range flows.ToAdd.Items {
Shrey Baid807a2a02020-04-09 12:52:45 +05301387 logger.Debugw("adding-flow",
1388 log.Fields{"device-id": device.Id,
1389 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001390 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1391 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001392 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1393 if err != nil {
1394 errorsList = append(errorsList, err)
1395 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301396 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001397 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001398
Girish Gowdracefae192020-03-19 18:14:10 -07001399 // 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 +00001400 if groups != nil {
1401 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001402 err := dh.flowMgr.AddGroup(ctx, group)
1403 if err != nil {
1404 errorsList = append(errorsList, err)
1405 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001406 }
1407 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001408 err := dh.flowMgr.ModifyGroup(ctx, group)
1409 if err != nil {
1410 errorsList = append(errorsList, err)
1411 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001412 }
1413 if len(groups.ToRemove.Items) != 0 {
Thomas Lee S985938d2020-05-04 11:40:41 +05301414 logger.Debugw("group-delete-operation-not-supported", log.Fields{"device-id": dh.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001415 }
1416 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001417 if len(errorsList) > 0 {
1418 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1419 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301420 logger.Debugw("updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001421 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301422}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001423
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001424//DisableDevice disables the given device
1425//It marks the following for the given device:
1426//Device-Handler Admin-State : down
1427//Device Port-State: UNKNOWN
1428//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001429func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001430 /* On device disable ,admin state update has to be done prior sending request to agent since
1431 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001432 if dh.Client != nil {
1433 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1434 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001435 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001436 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001437 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001438 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301439 logger.Debugw("olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001440 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001441 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301442
1443 dh.discOnus = sync.Map{}
1444 dh.onus = sync.Map{}
1445
Thomas Lee S85f37312020-04-03 17:06:12 +05301446 //stopping the stats collector
1447 dh.stopCollector <- true
1448
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301449 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001450 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301451 //Update device Admin state
1452 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001453 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1454 for _, port := range cloned.Ports {
1455 if port.GetType() == voltha.Port_PON_OLT {
1456 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1457 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001458 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001459 }
1460 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001461 }
1462
Shrey Baid807a2a02020-04-09 12:52:45 +05301463 logger.Debugw("disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001464 return nil
1465}
1466
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301467func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001468
1469 // Update onu state as unreachable in onu adapter
1470 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301471 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001472 //get the child device for the parent device
1473 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1474 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301475 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 -04001476 }
1477 if onuDevices != nil {
1478 for _, onuDevice := range onuDevices.Items {
1479 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1480 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1481 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001482 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301483 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001484 }
1485
1486 }
1487 }
1488
1489}
1490
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001491//ReenableDevice re-enables the olt device after disable
1492//It marks the following for the given device:
1493//Device-Handler Admin-State : up
1494//Device Port-State: ACTIVE
1495//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001496func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301497
1498 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1499 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001500 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301501 }
1502 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001503 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001504
1505 cloned := proto.Clone(device).(*voltha.Device)
1506 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001507
kdarapu1afeceb2020-02-12 01:38:09 -05001508 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001509 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001510 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001511 //Update the device oper status as ACTIVE
1512 cloned.OperStatus = voltha.OperStatus_ACTIVE
1513 dh.device = cloned
1514
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001515 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301516 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001517 "device-id": device.Id,
1518 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001519 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001520 }
kesavand39e0aa32020-01-28 20:58:50 -05001521
Shrey Baid807a2a02020-04-09 12:52:45 +05301522 logger.Debugw("reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001523
1524 return nil
1525}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001526
npujarec5762e2020-01-01 14:08:48 +05301527func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001528 var uniID uint32
1529 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301530 for _, port := range onu.UniPorts {
1531 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001532 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001533 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301534 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301535 logger.Debugw("failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001536 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301537 logger.Debugw("deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301538 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001539 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301540 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001541 }
npujarec5762e2020-01-01 14:08:48 +05301542 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001543 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301544 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301545 logger.Debugw("failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001546 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301547 logger.Debugw("removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301548 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301549 logger.Debugw("failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001550 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301551 logger.Debugw("removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301552 }
npujarec5762e2020-01-01 14:08:48 +05301553 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1554 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301555 logger.Debugw("failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301556 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301557 logger.Debugw("removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301558 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301559 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 +00001560 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001561 }
1562 return nil
1563}
1564
npujarec5762e2020-01-01 14:08:48 +05301565func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001566 nniUniID := -1
1567 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301568
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001569 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301570 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001571 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001572 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301573 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301574 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001575 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001576 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301577 logger.Debugw("nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301578 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301579 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Shrey Baid807a2a02020-04-09 12:52:45 +05301580 logger.Debugw("current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301581 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301582 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301583 }
npujarec5762e2020-01-01 14:08:48 +05301584 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001585 }
npujarec5762e2020-01-01 14:08:48 +05301586 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001587 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301588 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001589 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001590}
1591
1592// 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 +05301593func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301594 logger.Debug("function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001595 /* Clear the KV store data associated with the all the UNI ports
1596 This clears up flow data and also resource map data for various
1597 other pon resources like alloc_id and gemport_id
1598 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001599 go dh.cleanupDeviceResources(ctx)
Shrey Baid807a2a02020-04-09 12:52:45 +05301600 logger.Debug("removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001601 // Stop the Stats collector
1602 dh.stopCollector <- true
1603 // stop the heartbeat check routine
1604 dh.stopHeartbeatCheck <- true
1605 //Reset the state
1606 if dh.Client != nil {
1607 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301608 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001609 }
1610 }
1611 cloned := proto.Clone(device).(*voltha.Device)
1612 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1613 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1614 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1615 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1616 "device-id": device.Id,
1617 "connect-status": cloned.ConnectStatus,
1618 "oper-status": cloned.OperStatus}, err).Log()
1619 }
1620 return nil
1621}
1622func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001623 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301624 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1625 var ponPort uint32
1626 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1627 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301628 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301629 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301630 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001631 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001632 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301633 }
1634 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301635 onuID := make([]uint32, 1)
Shrey Baid807a2a02020-04-09 12:52:45 +05301636 logger.Debugw("onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301637 if err = dh.clearUNIData(ctx, &onu); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301638 logger.Errorw("failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301639 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301640 // Clear flowids for gem cache.
1641 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301642 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301643 }
1644 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301645 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301646 }
npujarec5762e2020-01-01 14:08:48 +05301647 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301648 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301649 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301650 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301651 logger.Errorw("failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001652 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001653 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001654 /* Clear the flows from KV store associated with NNI port.
1655 There are mostly trap rules from NNI port (like LLDP)
1656 */
npujarec5762e2020-01-01 14:08:48 +05301657 if err := dh.clearNNIData(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301658 logger.Errorw("failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001659 }
A R Karthick1f85b802019-10-11 05:06:05 +00001660
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001661 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301662 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001663 }
A R Karthick1f85b802019-10-11 05:06:05 +00001664
Devmalya Paul495b94a2019-08-27 19:42:00 -04001665 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301666 dh.onus.Range(func(key interface{}, value interface{}) bool {
1667 dh.onus.Delete(key)
1668 return true
1669 })
1670
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001671 /*Delete discovered ONU map for the device*/
1672 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1673 dh.discOnus.Delete(key)
1674 return true
1675 })
1676
Devmalya Paul495b94a2019-08-27 19:42:00 -04001677 return nil
1678}
1679
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001680//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001681func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1682 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301683 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001684 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301685 logger.Debugw("rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001686 return nil
1687}
1688
David K. Bainbridge794735f2020-02-11 21:01:37 -08001689func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301690 logger.Debugw("received-packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001691 "packet-indication": *packetIn,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001692 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001693 "packet": hex.EncodeToString(packetIn.Pkt),
1694 })
npujarec5762e2020-01-01 14:08:48 +05301695 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001696 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001697 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001698 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301699 logger.Debugw("sending-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001700 "logicalPortNum": logicalPortNum,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001701 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001702 "packet": hex.EncodeToString(packetIn.Pkt),
1703 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001704 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301705 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301707 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001708 "device-id": dh.device.Id,
1709 "packet": hex.EncodeToString(packetIn.Pkt),
1710 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001711 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301712 logger.Debugw("success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001713 "packet": hex.EncodeToString(packetIn.Pkt),
Thomas Lee S985938d2020-05-04 11:40:41 +05301714 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001715 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001716 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001717}
1718
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001719// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301720func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001721 logger.Debugw("incoming-packet-out", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301722 "device-id": dh.device.Id,
Shrey Baid807a2a02020-04-09 12:52:45 +05301723 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001724 "pkt-length": len(packet.Data),
1725 "packet": hex.EncodeToString(packet.Data),
1726 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001727
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001728 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001729 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001730 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1731 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301732 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1733 // Do not packet-out lldp packets on uni port.
1734 // ONOS has no clue about uni/nni ports, it just packets out on all
1735 // available ports on the Logical Switch. It should not be interested
1736 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001737 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1738 "device-id": dh.device.Id,
1739 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301740 return nil
1741 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001742 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1743 if innerEthType == 0x8100 {
1744 // q-in-q 802.1ad or 802.1q double tagged packet.
1745 // slice out the outer tag.
1746 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001747 logger.Debugw("packet-now-single-tagged", log.Fields{
1748 "packetData": hex.EncodeToString(packet.Data),
1749 "device-id": dh.device.Id,
1750 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001751 }
1752 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001753 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1754 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001755 uniID := UniIDFromPortNum(uint32(egressPortNo))
1756
npujarec5762e2020-01-01 14:08:48 +05301757 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001758 if err != nil {
1759 // In this case the openolt agent will receive the gemPortID as 0.
1760 // The agent tries to retrieve the gemPortID in this case.
1761 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001762 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001763 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301764 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001765 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001766 }
1767
1768 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001769
Girish Kumar2ad402b2020-03-20 19:45:12 +00001770 logger.Debugw("sending-packet-to-onu", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301771 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001772 "IntfId": intfID,
1773 "onuID": onuID,
1774 "uniID": uniID,
1775 "gemPortID": gemPortID,
1776 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301777 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001778 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001779
npujarec5762e2020-01-01 14:08:48 +05301780 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301781 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001782 "source": "adapter",
1783 "destination": "onu",
1784 "egress-port-number": egressPortNo,
1785 "interface-id": intfID,
1786 "oni-id": onuID,
1787 "uni-id": uniID,
1788 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001789 "packet": hex.EncodeToString(packet.Data),
1790 "device-id": dh.device.Id,
1791 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001792 }
1793 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001794 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1795 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001796 return olterrors.NewErrInvalidValue(log.Fields{
1797 "egress-nni-port": egressPortNo,
1798 "device-id": dh.device.Id,
1799 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001800 }
1801 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001802
Girish Kumar2ad402b2020-03-20 19:45:12 +00001803 logger.Debugw("sending-packet-to-nni", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301804 "uplink-pkt": uplinkPkt,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001805 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301806 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001807 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001808
npujarec5762e2020-01-01 14:08:48 +05301809 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001810 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1811 "packet": hex.EncodeToString(packet.Data),
1812 "device-id": dh.device.Id,
1813 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001814 }
1815 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301816 logger.Warnw("packet-out-to-this-interface-type-not-implemented", log.Fields{
1817 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001818 "egressPortType": egressPortType,
1819 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301820 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001821 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001822 }
1823 return nil
1824}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001825
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001826func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1827 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001828}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301829
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001830func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301831 // start the heartbeat check towards the OLT.
1832 var timerCheck *time.Timer
1833
1834 for {
1835 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1836 select {
1837 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001838 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1839 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301840 logger.Warnw("hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301841 if timerCheck == nil {
1842 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001843 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301844 }
1845 } else {
1846 if timerCheck != nil {
1847 if timerCheck.Stop() {
Thomas Lee S985938d2020-05-04 11:40:41 +05301848 logger.Debugw("got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301849 }
1850 timerCheck = nil
1851 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301852 logger.Debugw("hearbeat",
1853 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301854 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301855 }
1856 cancel()
1857 case <-dh.stopHeartbeatCheck:
Thomas Lee S985938d2020-05-04 11:40:41 +05301858 logger.Debugw("stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301859 return
1860 }
1861 }
1862}
1863
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001864func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1865 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1866 if err != nil || device == nil {
1867 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1868 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301869
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001870 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1871 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1872 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1873 }
1874 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1875 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1876 }
1877 go dh.cleanupDeviceResources(ctx)
1878
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001879 dh.lockDevice.RLock()
1880 // Stop the read indication only if it the routine is active
1881 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1882 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1883 // on next execution of the readIndication routine.
1884 if dh.isReadIndicationRoutineActive {
1885 dh.stopIndications <- true
1886 }
1887 dh.lockDevice.RUnlock()
1888
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001889 dh.transitionMap.Handle(ctx, DeviceInit)
1890
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301891 }
1892}
kesavand39e0aa32020-01-28 20:58:50 -05001893
1894// EnablePort to enable Pon interface
1895func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001896 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001897 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001898}
1899
1900// DisablePort to disable pon interface
1901func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001902 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001903 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001904}
1905
kdarapu1afeceb2020-02-12 01:38:09 -05001906//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1907func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301908 ctx := context.Background()
Thomas Lee S985938d2020-05-04 11:40:41 +05301909 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05001910 if port.GetType() == voltha.Port_ETHERNET_NNI {
1911 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001912 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301913 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301914 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001915 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001916 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001917 }
1918 // fetch interfaceid from PortNo
1919 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1920 ponIntf := &oop.Interface{IntfId: ponID}
1921 var operStatus voltha.OperStatus_Types
1922 if enablePort {
1923 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301924 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001925
1926 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301927 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001928 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001929 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001930 }
1931 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001932 dh.activePorts.Store(ponID, true)
Shrey Baid807a2a02020-04-09 12:52:45 +05301933 logger.Infow("enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001934 } else {
1935 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301936 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001937 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301938 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001939 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001940 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001941 }
1942 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001943 dh.activePorts.Store(ponID, false)
Shrey Baid807a2a02020-04-09 12:52:45 +05301944 logger.Infow("disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001945 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301946 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 +05301947 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301948 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001949 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001950 }
1951 return nil
1952}
1953
kdarapu1afeceb2020-02-12 01:38:09 -05001954//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1955func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001956 cloned := proto.Clone(device).(*voltha.Device)
1957 // Disable the port and update the oper_port_status to core
1958 // if the Admin state of the port is disabled on reboot and re-enable device.
1959 for _, port := range cloned.Ports {
1960 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001961 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301962 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301963 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001964 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001965 }
1966 }
1967 }
1968 return nil
1969}
1970
1971//populateActivePorts to populate activePorts map
1972func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301973 logger.Infow("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001974 for _, port := range device.Ports {
1975 if port.Type == voltha.Port_ETHERNET_NNI {
1976 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001977 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001978 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001979 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001980 }
1981 }
1982 if port.Type == voltha.Port_PON_OLT {
1983 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001984 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001985 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001986 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001987 }
1988 }
1989 }
1990}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001991
1992// ChildDeviceLost deletes ONU and clears pon resources related to it.
1993func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001994 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07001995 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1996 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001997 onuDevice, ok := dh.onus.Load(onuKey)
1998 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301999 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002000 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302001 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002002 "onu-id": onuID,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002003 "interface-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002004 }
2005 var sn *oop.SerialNumber
2006 var err error
2007 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302008 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002009 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302010 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002011 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2012 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002013
2014 for uniID := 0; uniID < MaxUnisPerOnu; uniID++ {
2015 var flowRemoveData pendingFlowRemoveData
2016 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uint32(uniID)}
2017 dh.lockDevice.RLock()
2018 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2019 dh.lockDevice.RUnlock()
2020 continue
2021 }
2022 dh.lockDevice.RUnlock()
2023
2024 log.Debugw("wait-for-flow-remove-complete-before-processing-child-device-lost",
2025 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2026 // Wait for all flow removes to finish first
2027 <-flowRemoveData.allFlowsRemoved
2028 log.Debugw("flow-removes-complete-for-subscriber",
2029 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2030 }
2031
2032 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002033 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302034 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302035 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002036 "onu-id": onuID}, err).Log()
2037 }
2038 //clear PON resources associated with ONU
2039 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002040 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002041 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302042 "device-id": dh.device.Id,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002043 "interface-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002044 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002045 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05302046 logger.Warnw("failed-to-get-onu-info-for-pon-port", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302047 "device-id": dh.device.Id,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002048 "interface-id": intfID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002049 "error": err})
2050 } else {
2051 for i, onu := range onuGemData {
2052 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Shrey Baid807a2a02020-04-09 12:52:45 +05302053 logger.Debugw("onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002054 if err := dh.clearUNIData(ctx, &onu); err != nil {
2055 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302056 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002057 "onu-device": onu,
2058 "error": err})
2059 }
2060 // Clear flowids for gem cache.
2061 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002062 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002063 }
2064 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002065 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002066 if err != nil {
2067 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002068 "interface-id": intfID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002069 "onu-device": onu,
2070 "onu-gem": onuGemData,
2071 "error": err})
2072 //Not returning error on cleanup.
2073 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002074 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
2075 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002076 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002077 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002078 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002079 }
2080 }
2081 dh.onus.Delete(onuKey)
2082 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2083 return nil
2084}
Girish Gowdracefae192020-03-19 18:14:10 -07002085
2086func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2087 for _, field := range flows.GetOfbFields(flow) {
2088 if field.Type == flows.IN_PORT {
2089 return field.GetPort()
2090 }
2091 }
2092 return InvalidPort
2093}
2094
2095func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2096 for _, action := range flows.GetActions(flow) {
2097 if action.Type == flows.OUTPUT {
2098 if out := action.GetOutput(); out != nil {
2099 return out.GetPort()
2100 }
2101 }
2102 }
2103 return InvalidPort
2104}
2105
2106func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2107 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302108 logger.Debugw("increment-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002109 if inPort != InvalidPort && outPort != InvalidPort {
2110 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2111 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302112 logger.Debugw("increment-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002113
2114 dh.lockDevice.Lock()
2115 defer dh.lockDevice.Unlock()
2116 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2117 if !ok {
2118 flowRemoveData = pendingFlowRemoveData{
2119 pendingFlowRemoveCount: 0,
2120 allFlowsRemoved: make(chan struct{}),
2121 }
2122 }
2123 flowRemoveData.pendingFlowRemoveCount++
2124 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2125
Shrey Baid807a2a02020-04-09 12:52:45 +05302126 logger.Debugw("current-flow-remove-count–increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002127 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2128 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2129 }
2130}
2131
2132func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2133 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302134 logger.Debugw("decrement-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002135 if inPort != InvalidPort && outPort != InvalidPort {
2136 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2137 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302138 logger.Debugw("decrement-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002139
2140 dh.lockDevice.Lock()
2141 defer dh.lockDevice.Unlock()
2142 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302143 logger.Fatalf("flow-remove-key-not-found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002144 } else {
2145 if val.pendingFlowRemoveCount > 0 {
2146 val.pendingFlowRemoveCount--
2147 }
Shrey Baid807a2a02020-04-09 12:52:45 +05302148 logger.Debugw("current-flow-remove-count-after-decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002149 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2150 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2151 // If all flow removes have finished, then close the channel to signal the receiver
2152 // to go ahead with flow adds.
2153 if val.pendingFlowRemoveCount == 0 {
2154 close(val.allFlowsRemoved)
2155 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2156 return
2157 }
2158 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2159 }
2160 }
2161}
2162
2163func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2164 var flowRemoveData pendingFlowRemoveData
2165 var ok bool
2166 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302167 logger.Debugw("wait-for-flow-remove-to-finish-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002168 if inPort != InvalidPort && outPort != InvalidPort {
2169 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2170 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302171 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 -07002172
2173 dh.lockDevice.RLock()
2174 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302175 logger.Debugw("no-pending-flow-to-remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002176 dh.lockDevice.RUnlock()
2177 return
2178 }
2179 dh.lockDevice.RUnlock()
2180
2181 // Wait for all flow removes to finish first
2182 <-flowRemoveData.allFlowsRemoved
2183
Shrey Baid807a2a02020-04-09 12:52:45 +05302184 logger.Debugw("all-flows-cleared--handling-flow-add-now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002185 }
2186}
2187
2188func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2189 inPort := getInPortFromFlow(flow)
2190 outPort := getOutPortFromFlow(flow)
2191
2192 if inPort == InvalidPort || outPort == InvalidPort {
2193 return inPort, outPort
2194 }
2195
2196 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2197 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2198 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2199 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2200 return uniPort, outPort
2201 }
2202 }
2203 } else {
2204 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2205 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2206 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2207 return inPort, uniPort
2208 }
2209 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2210 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2211 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2212 return uniPort, outPort
2213 }
2214 }
2215 }
2216
2217 return InvalidPort, InvalidPort
2218}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002219
2220func extractOmciTransactionID(omciPkt []byte) uint16 {
2221 if len(omciPkt) > 3 {
2222 d := omciPkt[0:2]
2223 transid := binary.BigEndian.Uint16(d)
2224 return transid
2225 }
2226 return 0
2227}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002228
2229// StoreOnuDevice stores the onu parameters to the local cache.
2230func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2231 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2232 dh.onus.Store(onuKey, onuDevice)
2233}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002234
Devmalya Paula1efa642020-04-20 01:36:43 -04002235// setOnuITUPonAlarmConfig sets the parameters in the openolt agent for raising the ONU ITU PON alarms.
2236func (dh *DeviceHandler) setOnuITUPonAlarmConfig(config *oop.OnuItuPonAlarm) error {
2237 if _, err := dh.Client.OnuItuPonAlarmSet(context.Background(), config); err != nil {
2238 return err
2239 }
2240 logger.Debugw("onu-itu-pon-alarm-config-set-successful", log.Fields{"config": config})
2241 return nil
2242}
2243
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002244func (dh *DeviceHandler) getExtValue(device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
2245 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002246 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002247 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002248 resp := new(voltha.ReturnValues)
2249 valueparam := new(oop.ValueParam)
2250 ctx := context.Background()
2251 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002252 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2253 return nil, err
2254 }
2255 ID = device.ProxyAddress.GetOnuId()
2256 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2257 valueparam.Onu = &Onu
2258 valueparam.Value = value
2259
2260 // This API is unsupported until agent patch is added
2261 resp.Unsupported = uint32(value)
2262 _ = ctx
2263
2264 // Uncomment this code once agent changes are complete and tests
2265 /*
2266 resp, err = dh.Client.GetValue(ctx, valueparam)
2267 if err != nil {
2268 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2269 return nil, err
2270 }
2271 */
2272
2273 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2274 return resp, nil
2275}