blob: 39775a0a17b2057365e61769572f165c42492071 [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 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400715 // Instantiate resource manager
Neha Sharma3f221ae2020-04-29 19:02:12 +0000716 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, deviceInfo); dh.resourceMgr == nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400717 return olterrors.ErrResourceManagerInstantiating
718 }
719
720 // Instantiate flow manager
721 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
722 return olterrors.ErrResourceManagerInstantiating
723
724 }
725 /* TODO: Instantiate Alarm , stats , BW managers */
726 /* Instantiating Event Manager to handle Alarms and KPIs */
727 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
728
729 // Stats config for new device
730 dh.portStats = NewOpenOltStatsMgr(dh)
731
732 return nil
733
734}
735
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400736func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
737 var err error
738 var deviceInfo *oop.DeviceInfo
739
740 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
741
742 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000743 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400744 }
745 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000746 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400747 }
748
Thomas Lee S985938d2020-05-04 11:40:41 +0530749 logger.Debugw("fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400750 dh.device.Root = true
751 dh.device.Vendor = deviceInfo.Vendor
752 dh.device.Model = deviceInfo.Model
753 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
754 dh.device.HardwareVersion = deviceInfo.HardwareVersion
755 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
756
757 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000758 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400759 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
760 genmac, err := generateMacFromHost(host)
761 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000762 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400763 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000764 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400765 dh.device.MacAddress = genmac
766 } else {
767 dh.device.MacAddress = deviceInfo.DeviceId
768 }
769
770 // Synchronous call to update device - this method is run in its own go routine
771 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000772 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400773 }
774
775 return deviceInfo, nil
776}
777
Naga Manjunath7615e552019-10-11 22:35:47 +0530778func startCollector(dh *DeviceHandler) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530779 logger.Debugf("starting-collector")
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530780 freq := dh.metrics.ToPmConfigs().DefaultFreq
Naga Manjunath7615e552019-10-11 22:35:47 +0530781 for {
782 select {
783 case <-dh.stopCollector:
Thomas Lee S985938d2020-05-04 11:40:41 +0530784 logger.Debugw("stopping-collector-for-olt", log.Fields{"deviceID:": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530785 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530786 case <-time.After(time.Duration(freq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700787
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530788 ports := make([]*voltha.Port, len(dh.device.Ports))
789 copy(ports, dh.device.Ports)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530790 for _, port := range ports {
791 // NNI Stats
792 if port.Type == voltha.Port_ETHERNET_NNI {
793 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
794 cmnni := dh.portStats.collectNNIMetrics(intfID)
795 logger.Debugw("collect-nni-metrics", log.Fields{"metrics": cmnni})
Girish Gowdra34815db2020-05-11 17:18:04 -0700796 go dh.portStats.publishMetrics(cmnni, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530797 logger.Debugw("publish-nni-metrics", log.Fields{"nni-port": port.Label})
798 }
799 // PON Stats
800 if port.Type == voltha.Port_PON_OLT {
801 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
802 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
803 cmpon := dh.portStats.collectPONMetrics(intfID)
804 logger.Debugw("collect-pon-metrics", log.Fields{"metrics": cmpon})
Girish Gowdra34815db2020-05-11 17:18:04 -0700805 go dh.portStats.publishMetrics(cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530806 }
807 logger.Debugw("publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500808 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530809 }
810 }
811 }
812}
813
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700814//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530815func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400816 dh.transitionMap = NewTransitionMap(dh)
Shrey Baid807a2a02020-04-09 12:52:45 +0530817 logger.Infow("adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530818 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530819
820 // Now, set the initial PM configuration for that device
821 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530822 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530823 }
824
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400825 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530826}
827
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700828//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530829func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700830 return &ic.SwitchCapability{
831 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530832 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700833 HwDesc: "open_pon",
834 SwDesc: "open_pon",
835 SerialNum: dh.device.SerialNumber,
836 },
837 SwitchFeatures: &of.OfpSwitchFeatures{
838 NBuffers: 256,
839 NTables: 2,
840 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
841 of.OfpCapabilities_OFPC_TABLE_STATS |
842 of.OfpCapabilities_OFPC_PORT_STATS |
843 of.OfpCapabilities_OFPC_GROUP_STATS),
844 },
845 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530846}
847
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700848//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530849func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700850 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700851 return &ic.PortCapability{
852 Port: &voltha.LogicalPort{
853 OfpPort: &of.OfpPort{
854 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
855 Config: 0,
856 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700857 Curr: capacity,
858 Advertised: capacity,
859 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700860 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
861 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
862 },
863 DeviceId: dh.device.Id,
864 DevicePortNo: uint32(portNo),
865 },
866 }, nil
867}
868
David K. Bainbridge794735f2020-02-11 21:01:37 -0800869func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530870 logger.Debugw("omci-indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700871 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700872 var deviceID string
873 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700874
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400875 transid := extractOmciTransactionID(omciInd.Pkt)
Thomas Lee S985938d2020-05-04 11:40:41 +0530876 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 -0400877 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
878
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700879 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530880
881 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
882
Thomas Lee S985938d2020-05-04 11:40:41 +0530883 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 -0700884 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700885 kwargs := make(map[string]interface{})
886 kwargs["onu_id"] = omciInd.OnuId
887 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700888
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700889 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
890 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530891 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000893 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700894 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700895 deviceType = onuDevice.Type
896 deviceID = onuDevice.Id
897 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
898 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530899 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700900 } else {
901 //found in cache
Thomas Lee S985938d2020-05-04 11:40:41 +0530902 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 +0530903 deviceType = onuInCache.(*OnuDevice).deviceType
904 deviceID = onuInCache.(*OnuDevice).deviceID
905 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700906 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700907
908 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800909 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Thomas Lee S985938d2020-05-04 11:40:41 +0530910 ic.InterAdapterMessageType_OMCI_REQUEST, dh.device.Type, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800911 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530912 return olterrors.NewErrCommunication("omci-request", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530913 "source": dh.device.Type,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800914 "destination": deviceType,
915 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000916 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700917 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800918 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530919}
920
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700921//ProcessInterAdapterMessage sends the proxied messages to the target device
922// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
923// is meant, and then send the unmarshalled omci message to this onu
924func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530925 logger.Debugw("process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700926 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700927 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700928 fromTopic := msg.Header.FromTopic
929 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700930 toDeviceID := msg.Header.ToDeviceId
931 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700932
Shrey Baid807a2a02020-04-09 12:52:45 +0530933 logger.Debugw("omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700934
935 msgBody := msg.GetBody()
936
937 omciMsg := &ic.InterAdapterOmciMessage{}
938 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000939 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700940 }
941
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700942 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700943 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
944 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530945 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800946 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000947 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700948 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530949 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 -0800950 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530951 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800952 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000953 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800954 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700955 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +0530956 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 -0800957 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530958 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800959 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000960 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800961 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700962 }
963
964 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000965 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700966 }
967 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530968}
969
David K. Bainbridge794735f2020-02-11 21:01:37 -0800970func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700971 var intfID uint32
972 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000973 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700974 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700975 intfID = onuDevice.ProxyAddress.GetChannelId()
976 onuID = onuDevice.ProxyAddress.GetOnuId()
977 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700978 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700979 intfID = omciMsg.GetProxyAddress().GetChannelId()
980 onuID = omciMsg.GetProxyAddress().GetOnuId()
981 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700982 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700983 if connectStatus != voltha.ConnectStatus_REACHABLE {
Shrey Baid807a2a02020-04-09 12:52:45 +0530984 logger.Debugw("onu-not-reachable--cannot-send-omci", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800985
Thomas Lee S94109f12020-03-03 16:39:29 +0530986 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800987 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000988 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700989 }
990
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400991 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
992 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700993 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400994 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
995 hex.Encode(hexPkt, omciMsg.Message)
996 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
997
998 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
999 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1000 transid := extractOmciTransactionID(omciMsg.Message)
1001 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
1002 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001003
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001004 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
1005 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301006 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001007 "interface-id": intfID,
1008 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001009 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001010 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001011 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001012}
1013
David K. Bainbridge794735f2020-02-11 21:01:37 -08001014func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301015 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 +02001016 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
1017 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
1018 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001019 // TODO: need resource manager
1020 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301022 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001023 st, _ := status.FromError(err)
1024 if st.Code() == codes.AlreadyExists {
Thomas Lee S985938d2020-05-04 11:40:41 +05301025 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 -04001026 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301027 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001028 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001029 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301030 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001031 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001032 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001033}
1034
David K. Bainbridge794735f2020-02-11 21:01:37 -08001035func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001036
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001037 channelID := onuDiscInd.GetIntfId()
1038 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001039
Girish Kumar2ad402b2020-03-20 19:45:12 +00001040 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301041
cuilin20187b2a8c32019-03-26 19:52:28 -07001042 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001043 if sn != "" {
1044 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001045 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001046 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001047 }
1048
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301049 var alarmInd oop.OnuAlarmIndication
1050 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001051 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301052
1053 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1054 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1055 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1056 OnuLosRaise event sent for it */
1057 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1058 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1059 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Shrey Baid807a2a02020-04-09 12:52:45 +05301060 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301061 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1062 "currentIntfId": onuDiscInd.GetIntfId()})
1063 // TODO:: Should we need to ignore raising OnuLosClear event
1064 // when onu connected to different PON?
1065 }
1066 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1067 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1068 alarmInd.LosStatus = statusCheckOff
1069 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1070 }
1071 return true
1072 })
1073
Girish Kumar2ad402b2020-03-20 19:45:12 +00001074 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001075 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001076 }
1077
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001078 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001079
1080 // check the ONU is already know to the OLT
1081 // NOTE the second time the ONU is discovered this should return a device
1082 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1083
1084 if err != nil {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001085 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 -08001086 if e, ok := status.FromError(err); ok {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001087 logger.Debugw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001088 switch e.Code() {
1089 case codes.Internal:
1090 // this probably means NOT FOUND, so just create a new device
1091 onuDevice = nil
1092 case codes.DeadlineExceeded:
1093 // if the call times out, cleanup and exit
1094 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001095 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001096 }
1097 }
1098 }
1099
1100 if onuDevice == nil {
1101 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001102 logger.Debugw("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001103 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001104 ponintfid := onuDiscInd.GetIntfId()
1105 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301106 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001107 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001108
Girish Kumar2ad402b2020-03-20 19:45:12 +00001109 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001110
1111 if err != nil {
1112 // if we can't create an ID in resource manager,
1113 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001114 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001115 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001117 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001118 }
1119
1120 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1121 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001122 dh.discOnus.Delete(sn)
1123 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 +05301124 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001126 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001127 }
Amit Ghosh75f0e292020-05-14 11:31:54 +01001128 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Shrey Baid807a2a02020-04-09 12:52:45 +05301129 logger.Infow("onu-child-device-added",
1130 log.Fields{"onuDevice": onuDevice,
1131 "sn": sn,
1132 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301133 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001134 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001135
1136 // we can now use the existing ONU Id
1137 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001138 //Insert the ONU into cache to use in OnuIndication.
1139 //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 +05301140 logger.Debugw("onu-discovery-indication-key-create",
1141 log.Fields{"onuID": onuID,
1142 "intfId": onuDiscInd.GetIntfId(),
1143 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001144 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001145
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301146 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301147 dh.onus.Store(onuKey, onuDev)
Shrey Baid807a2a02020-04-09 12:52:45 +05301148 logger.Debugw("new-onu-device-discovered",
1149 log.Fields{"onu": onuDev,
1150 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001151
David K. Bainbridge794735f2020-02-11 21:01:37 -08001152 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301153 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001154 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001155 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001156 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301157 logger.Infow("onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001158 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301159 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001161 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001162 }
1163 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001164}
1165
David K. Bainbridge794735f2020-02-11 21:01:37 -08001166func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001167 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1168
1169 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001170 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001171 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001172 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001173 foundInCache := false
Shrey Baid807a2a02020-04-09 12:52:45 +05301174 logger.Debugw("onu-indication-key-create",
1175 log.Fields{"onuId": onuInd.OnuId,
1176 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301177 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001178 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301179
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 errFields := log.Fields{"device-id": dh.device.Id}
1181
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301182 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1183
Mahir Gunyele77977b2019-06-27 05:36:22 -07001184 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1185 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1187 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001188 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001189 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1190 if serialNumber != "" {
1191 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001193 } else {
1194 kwargs["onu_id"] = onuInd.OnuId
1195 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 errFields["onu-id"] = onuInd.OnuId
1197 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001198 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001199 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001200 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001201
David K. Bainbridge794735f2020-02-11 21:01:37 -08001202 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001203 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001204 }
1205
David K. Bainbridge794735f2020-02-11 21:01:37 -08001206 if onuDevice.ParentPortNo != ponPort {
Shrey Baid807a2a02020-04-09 12:52:45 +05301207 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 "previousIntfId": onuDevice.ParentPortNo,
1209 "currentIntfId": ponPort})
1210 }
1211
1212 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Shrey Baid807a2a02020-04-09 12:52:45 +05301213 logger.Warnw("onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
1214 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1215 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301216 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001217 }
1218 if !foundInCache {
1219 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1220
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301221 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 -08001222
1223 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001224 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001225 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001226 }
1227 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001228}
1229
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001230func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301231 ctx := context.TODO()
Shrey Baid807a2a02020-04-09 12:52:45 +05301232 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 +00001233 if onuInd.AdminState == "down" {
Girish Gowdra429f9502020-05-04 13:22:16 -07001234 // The ONU has gone admin_state "down" and we expect the ONU to send discovery again
1235 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001236 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1237 if onuInd.OperState != "down" {
Shrey Baid807a2a02020-04-09 12:52:45 +05301238 logger.Warnw("onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001239 onuInd.OperState = "down"
1240 }
1241 }
1242
David K. Bainbridge794735f2020-02-11 21:01:37 -08001243 switch onuInd.OperState {
1244 case "down":
Shrey Baid807a2a02020-04-09 12:52:45 +05301245 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 -07001246 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301247 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001248 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1249 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301250 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 "onu-indicator": onuInd,
1252 "source": "openolt",
1253 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001254 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001255 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 case "up":
Shrey Baid807a2a02020-04-09 12:52:45 +05301257 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 -04001258 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301259 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001260 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1261 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301262 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 "onu-indicator": onuInd,
1264 "source": "openolt",
1265 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001266 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001267 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001268 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001269 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001270 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001271 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001272}
1273
cuilin20187b2a8c32019-03-26 19:52:28 -07001274func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1275 if serialNum != nil {
1276 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001277 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001278 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001279}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001280func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1281 decodedStr, err := hex.DecodeString(serialNum[4:])
1282 if err != nil {
1283 return nil, err
1284 }
1285 return &oop.SerialNumber{
1286 VendorId: []byte(serialNum[:4]),
1287 VendorSpecific: []byte(decodedStr),
1288 }, nil
1289}
cuilin20187b2a8c32019-03-26 19:52:28 -07001290
1291func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1292 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001293 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001294 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1295 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1296 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1297 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1298 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1299 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1300 return tmp
1301}
1302
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303//UpdateFlowsBulk upates the bulk flow
1304func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301305 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001306}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001307
1308//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001309func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301310 logger.Debugw("getchilddevice",
1311 log.Fields{"pon-port": parentPort,
1312 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301313 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001314 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001315 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001316 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001318 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001319 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001320 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001321 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001322 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301323 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 -08001324 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301325}
1326
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001327// SendPacketInToCore sends packet-in to core
1328// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1329// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001330func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001331 logger.Debugw("send-packet-in-to-core", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301332 "port": logicalPort,
1333 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301334 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001335 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001336 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301337 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338 "source": "adapter",
1339 "destination": "core",
1340 "device-id": dh.device.Id,
1341 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001342 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001343 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301344 logger.Debugw("sent-packet-in-to-core-successfully", log.Fields{
1345 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301346 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001347 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001348 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001349}
1350
A R Karthick1f85b802019-10-11 05:06:05 +00001351// AddUniPortToOnu adds the uni port to the onu device
1352func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1353 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301354
1355 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001356 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301357 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1358 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001359 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001360 }
1361 }
1362}
1363
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001364//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301365func (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 +05301366 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 +01001367
1368 var errorsList []error
1369
Girish Gowdru0c588b22019-04-23 23:24:56 -04001370 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001371 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001372 dh.incrementActiveFlowRemoveCount(flow)
1373
Shrey Baid807a2a02020-04-09 12:52:45 +05301374 logger.Debugw("removing-flow",
1375 log.Fields{"device-id": device.Id,
1376 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001377 err := dh.flowMgr.RemoveFlow(ctx, flow)
1378 if err != nil {
1379 errorsList = append(errorsList, err)
1380 }
1381
1382 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001383 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301384
1385 for _, flow := range flows.ToAdd.Items {
Shrey Baid807a2a02020-04-09 12:52:45 +05301386 logger.Debugw("adding-flow",
1387 log.Fields{"device-id": device.Id,
1388 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001389 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1390 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001391 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1392 if err != nil {
1393 errorsList = append(errorsList, err)
1394 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301395 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001396 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001397
Girish Gowdracefae192020-03-19 18:14:10 -07001398 // 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 +00001399 if groups != nil {
1400 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001401 err := dh.flowMgr.AddGroup(ctx, group)
1402 if err != nil {
1403 errorsList = append(errorsList, err)
1404 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001405 }
1406 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001407 err := dh.flowMgr.ModifyGroup(ctx, group)
1408 if err != nil {
1409 errorsList = append(errorsList, err)
1410 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001411 }
1412 if len(groups.ToRemove.Items) != 0 {
Thomas Lee S985938d2020-05-04 11:40:41 +05301413 logger.Debugw("group-delete-operation-not-supported", log.Fields{"device-id": dh.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001414 }
1415 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001416 if len(errorsList) > 0 {
1417 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1418 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301419 logger.Debugw("updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001420 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301421}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001422
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001423//DisableDevice disables the given device
1424//It marks the following for the given device:
1425//Device-Handler Admin-State : down
1426//Device Port-State: UNKNOWN
1427//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001428func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001429 /* On device disable ,admin state update has to be done prior sending request to agent since
1430 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001431 if dh.Client != nil {
1432 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1433 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001434 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001435 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001436 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001437 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301438 logger.Debugw("olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001439 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001440 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301441
1442 dh.discOnus = sync.Map{}
1443 dh.onus = sync.Map{}
1444
Thomas Lee S85f37312020-04-03 17:06:12 +05301445 //stopping the stats collector
1446 dh.stopCollector <- true
1447
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301448 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001449 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301450 //Update device Admin state
1451 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001452 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1453 for _, port := range cloned.Ports {
1454 if port.GetType() == voltha.Port_PON_OLT {
1455 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1456 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001457 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001458 }
1459 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001460 }
1461
Shrey Baid807a2a02020-04-09 12:52:45 +05301462 logger.Debugw("disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001463 return nil
1464}
1465
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301466func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001467
1468 // Update onu state as unreachable in onu adapter
1469 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301470 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001471 //get the child device for the parent device
1472 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1473 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301474 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 -04001475 }
1476 if onuDevices != nil {
1477 for _, onuDevice := range onuDevices.Items {
1478 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1479 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1480 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001481 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301482 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001483 }
1484
1485 }
1486 }
1487
1488}
1489
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001490//ReenableDevice re-enables the olt device after disable
1491//It marks the following for the given device:
1492//Device-Handler Admin-State : up
1493//Device Port-State: ACTIVE
1494//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001495func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301496
1497 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1498 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001499 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301500 }
1501 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001502 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001503
1504 cloned := proto.Clone(device).(*voltha.Device)
1505 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001506
kdarapu1afeceb2020-02-12 01:38:09 -05001507 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001508 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001509 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001510 //Update the device oper status as ACTIVE
1511 cloned.OperStatus = voltha.OperStatus_ACTIVE
1512 dh.device = cloned
1513
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001514 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301515 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001516 "device-id": device.Id,
1517 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001518 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001519 }
kesavand39e0aa32020-01-28 20:58:50 -05001520
Shrey Baid807a2a02020-04-09 12:52:45 +05301521 logger.Debugw("reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001522
1523 return nil
1524}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001525
npujarec5762e2020-01-01 14:08:48 +05301526func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001527 var uniID uint32
1528 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301529 for _, port := range onu.UniPorts {
1530 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001531 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001532 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301533 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301534 logger.Debugw("failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001535 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301536 logger.Debugw("deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301537 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001538 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301539 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001540 }
npujarec5762e2020-01-01 14:08:48 +05301541 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001542 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301543 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301544 logger.Debugw("failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001545 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301546 logger.Debugw("removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301547 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301548 logger.Debugw("failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001549 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301550 logger.Debugw("removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301551 }
npujarec5762e2020-01-01 14:08:48 +05301552 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1553 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301554 logger.Debugw("failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301555 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301556 logger.Debugw("removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301557 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301558 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 +00001559 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001560 }
1561 return nil
1562}
1563
npujarec5762e2020-01-01 14:08:48 +05301564func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001565 nniUniID := -1
1566 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301567
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001568 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301569 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001570 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001571 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301572 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301573 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001574 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001575 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301576 logger.Debugw("nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301577 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301578 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Shrey Baid807a2a02020-04-09 12:52:45 +05301579 logger.Debugw("current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301580 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301581 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301582 }
npujarec5762e2020-01-01 14:08:48 +05301583 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001584 }
npujarec5762e2020-01-01 14:08:48 +05301585 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001586 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301587 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001588 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001589}
1590
1591// 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 +05301592func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301593 logger.Debug("function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001594 /* Clear the KV store data associated with the all the UNI ports
1595 This clears up flow data and also resource map data for various
1596 other pon resources like alloc_id and gemport_id
1597 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001598 go dh.cleanupDeviceResources(ctx)
Shrey Baid807a2a02020-04-09 12:52:45 +05301599 logger.Debug("removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001600 // Stop the Stats collector
1601 dh.stopCollector <- true
1602 // stop the heartbeat check routine
1603 dh.stopHeartbeatCheck <- true
1604 //Reset the state
1605 if dh.Client != nil {
1606 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301607 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001608 }
1609 }
1610 cloned := proto.Clone(device).(*voltha.Device)
1611 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1612 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1613 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1614 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1615 "device-id": device.Id,
1616 "connect-status": cloned.ConnectStatus,
1617 "oper-status": cloned.OperStatus}, err).Log()
1618 }
1619 return nil
1620}
1621func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001622 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301623 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1624 var ponPort uint32
1625 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1626 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301627 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301628 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301629 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001630 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001631 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301632 }
1633 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301634 onuID := make([]uint32, 1)
Shrey Baid807a2a02020-04-09 12:52:45 +05301635 logger.Debugw("onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301636 if err = dh.clearUNIData(ctx, &onu); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301637 logger.Errorw("failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301638 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301639 // Clear flowids for gem cache.
1640 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301641 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301642 }
1643 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301644 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301645 }
npujarec5762e2020-01-01 14:08:48 +05301646 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301647 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301648 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301649 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301650 logger.Errorw("failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001651 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001652 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001653 /* Clear the flows from KV store associated with NNI port.
1654 There are mostly trap rules from NNI port (like LLDP)
1655 */
npujarec5762e2020-01-01 14:08:48 +05301656 if err := dh.clearNNIData(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301657 logger.Errorw("failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001658 }
A R Karthick1f85b802019-10-11 05:06:05 +00001659
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001660 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301661 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001662 }
A R Karthick1f85b802019-10-11 05:06:05 +00001663
Devmalya Paul495b94a2019-08-27 19:42:00 -04001664 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301665 dh.onus.Range(func(key interface{}, value interface{}) bool {
1666 dh.onus.Delete(key)
1667 return true
1668 })
1669
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001670 /*Delete discovered ONU map for the device*/
1671 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1672 dh.discOnus.Delete(key)
1673 return true
1674 })
1675
Devmalya Paul495b94a2019-08-27 19:42:00 -04001676 return nil
1677}
1678
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001679//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001680func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1681 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301682 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001683 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301684 logger.Debugw("rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001685 return nil
1686}
1687
David K. Bainbridge794735f2020-02-11 21:01:37 -08001688func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301689 logger.Debugw("received-packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001690 "packet-indication": *packetIn,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001691 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001692 "packet": hex.EncodeToString(packetIn.Pkt),
1693 })
npujarec5762e2020-01-01 14:08:48 +05301694 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001695 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001696 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001697 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301698 logger.Debugw("sending-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001699 "logicalPortNum": logicalPortNum,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001700 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001701 "packet": hex.EncodeToString(packetIn.Pkt),
1702 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001703 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301704 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001705 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301706 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001707 "device-id": dh.device.Id,
1708 "packet": hex.EncodeToString(packetIn.Pkt),
1709 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001710 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301711 logger.Debugw("success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001712 "packet": hex.EncodeToString(packetIn.Pkt),
Thomas Lee S985938d2020-05-04 11:40:41 +05301713 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001714 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001715 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001716}
1717
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001718// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301719func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001720 logger.Debugw("incoming-packet-out", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301721 "device-id": dh.device.Id,
Shrey Baid807a2a02020-04-09 12:52:45 +05301722 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001723 "pkt-length": len(packet.Data),
1724 "packet": hex.EncodeToString(packet.Data),
1725 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001726
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001727 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001728 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001729 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1730 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301731 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1732 // Do not packet-out lldp packets on uni port.
1733 // ONOS has no clue about uni/nni ports, it just packets out on all
1734 // available ports on the Logical Switch. It should not be interested
1735 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001736 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1737 "device-id": dh.device.Id,
1738 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301739 return nil
1740 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001741 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1742 if innerEthType == 0x8100 {
1743 // q-in-q 802.1ad or 802.1q double tagged packet.
1744 // slice out the outer tag.
1745 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001746 logger.Debugw("packet-now-single-tagged", log.Fields{
1747 "packetData": hex.EncodeToString(packet.Data),
1748 "device-id": dh.device.Id,
1749 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001750 }
1751 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001752 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1753 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001754 uniID := UniIDFromPortNum(uint32(egressPortNo))
1755
npujarec5762e2020-01-01 14:08:48 +05301756 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001757 if err != nil {
1758 // In this case the openolt agent will receive the gemPortID as 0.
1759 // The agent tries to retrieve the gemPortID in this case.
1760 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001761 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001762 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301763 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001764 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001765 }
1766
1767 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001768
Girish Kumar2ad402b2020-03-20 19:45:12 +00001769 logger.Debugw("sending-packet-to-onu", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301770 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001771 "IntfId": intfID,
1772 "onuID": onuID,
1773 "uniID": uniID,
1774 "gemPortID": gemPortID,
1775 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301776 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001777 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001778
npujarec5762e2020-01-01 14:08:48 +05301779 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301780 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001781 "source": "adapter",
1782 "destination": "onu",
1783 "egress-port-number": egressPortNo,
1784 "interface-id": intfID,
1785 "oni-id": onuID,
1786 "uni-id": uniID,
1787 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001788 "packet": hex.EncodeToString(packet.Data),
1789 "device-id": dh.device.Id,
1790 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001791 }
1792 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001793 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1794 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001795 return olterrors.NewErrInvalidValue(log.Fields{
1796 "egress-nni-port": egressPortNo,
1797 "device-id": dh.device.Id,
1798 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001799 }
1800 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001801
Girish Kumar2ad402b2020-03-20 19:45:12 +00001802 logger.Debugw("sending-packet-to-nni", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301803 "uplink-pkt": uplinkPkt,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001804 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301805 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001806 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001807
npujarec5762e2020-01-01 14:08:48 +05301808 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001809 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1810 "packet": hex.EncodeToString(packet.Data),
1811 "device-id": dh.device.Id,
1812 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001813 }
1814 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301815 logger.Warnw("packet-out-to-this-interface-type-not-implemented", log.Fields{
1816 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001817 "egressPortType": egressPortType,
1818 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301819 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001820 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001821 }
1822 return nil
1823}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001824
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001825func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1826 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001827}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301828
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001829func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301830 // start the heartbeat check towards the OLT.
1831 var timerCheck *time.Timer
1832
1833 for {
1834 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1835 select {
1836 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001837 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1838 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301839 logger.Warnw("hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301840 if timerCheck == nil {
1841 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001842 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301843 }
1844 } else {
1845 if timerCheck != nil {
1846 if timerCheck.Stop() {
Thomas Lee S985938d2020-05-04 11:40:41 +05301847 logger.Debugw("got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301848 }
1849 timerCheck = nil
1850 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301851 logger.Debugw("hearbeat",
1852 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301853 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301854 }
1855 cancel()
1856 case <-dh.stopHeartbeatCheck:
Thomas Lee S985938d2020-05-04 11:40:41 +05301857 logger.Debugw("stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301858 return
1859 }
1860 }
1861}
1862
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001863func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1864 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1865 if err != nil || device == nil {
1866 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1867 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301868
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001869 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1870 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1871 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1872 }
1873 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1874 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1875 }
1876 go dh.cleanupDeviceResources(ctx)
1877
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001878 dh.lockDevice.RLock()
1879 // Stop the read indication only if it the routine is active
1880 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1881 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1882 // on next execution of the readIndication routine.
1883 if dh.isReadIndicationRoutineActive {
1884 dh.stopIndications <- true
1885 }
1886 dh.lockDevice.RUnlock()
1887
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001888 dh.transitionMap.Handle(ctx, DeviceInit)
1889
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301890 }
1891}
kesavand39e0aa32020-01-28 20:58:50 -05001892
1893// EnablePort to enable Pon interface
1894func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001895 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001896 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001897}
1898
1899// DisablePort to disable pon interface
1900func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001901 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001902 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001903}
1904
kdarapu1afeceb2020-02-12 01:38:09 -05001905//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1906func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301907 ctx := context.Background()
Thomas Lee S985938d2020-05-04 11:40:41 +05301908 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05001909 if port.GetType() == voltha.Port_ETHERNET_NNI {
1910 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001911 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301912 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301913 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001914 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001915 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001916 }
1917 // fetch interfaceid from PortNo
1918 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1919 ponIntf := &oop.Interface{IntfId: ponID}
1920 var operStatus voltha.OperStatus_Types
1921 if enablePort {
1922 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301923 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001924
1925 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301926 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001927 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001928 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001929 }
1930 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001931 dh.activePorts.Store(ponID, true)
Shrey Baid807a2a02020-04-09 12:52:45 +05301932 logger.Infow("enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001933 } else {
1934 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301935 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001936 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301937 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001938 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001939 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001940 }
1941 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001942 dh.activePorts.Store(ponID, false)
Shrey Baid807a2a02020-04-09 12:52:45 +05301943 logger.Infow("disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001944 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301945 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 +05301946 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301947 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001948 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001949 }
1950 return nil
1951}
1952
kdarapu1afeceb2020-02-12 01:38:09 -05001953//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1954func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001955 cloned := proto.Clone(device).(*voltha.Device)
1956 // Disable the port and update the oper_port_status to core
1957 // if the Admin state of the port is disabled on reboot and re-enable device.
1958 for _, port := range cloned.Ports {
1959 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001960 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301961 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301962 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001963 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001964 }
1965 }
1966 }
1967 return nil
1968}
1969
1970//populateActivePorts to populate activePorts map
1971func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301972 logger.Infow("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001973 for _, port := range device.Ports {
1974 if port.Type == voltha.Port_ETHERNET_NNI {
1975 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001976 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001977 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001978 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001979 }
1980 }
1981 if port.Type == voltha.Port_PON_OLT {
1982 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001983 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001984 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001985 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001986 }
1987 }
1988 }
1989}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001990
1991// ChildDeviceLost deletes ONU and clears pon resources related to it.
1992func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001993 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07001994 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1995 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001996 onuDevice, ok := dh.onus.Load(onuKey)
1997 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301998 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001999 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302000 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002001 "onu-id": onuID,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002002 "interface-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002003 }
2004 var sn *oop.SerialNumber
2005 var err error
2006 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302007 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002008 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302009 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002010 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2011 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002012
2013 for uniID := 0; uniID < MaxUnisPerOnu; uniID++ {
2014 var flowRemoveData pendingFlowRemoveData
2015 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uint32(uniID)}
2016 dh.lockDevice.RLock()
2017 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2018 dh.lockDevice.RUnlock()
2019 continue
2020 }
2021 dh.lockDevice.RUnlock()
2022
2023 log.Debugw("wait-for-flow-remove-complete-before-processing-child-device-lost",
2024 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2025 // Wait for all flow removes to finish first
2026 <-flowRemoveData.allFlowsRemoved
2027 log.Debugw("flow-removes-complete-for-subscriber",
2028 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2029 }
2030
2031 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002032 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302033 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302034 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002035 "onu-id": onuID}, err).Log()
2036 }
2037 //clear PON resources associated with ONU
2038 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002039 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002040 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302041 "device-id": dh.device.Id,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002042 "interface-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002043 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002044 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05302045 logger.Warnw("failed-to-get-onu-info-for-pon-port", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302046 "device-id": dh.device.Id,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002047 "interface-id": intfID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002048 "error": err})
2049 } else {
2050 for i, onu := range onuGemData {
2051 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Shrey Baid807a2a02020-04-09 12:52:45 +05302052 logger.Debugw("onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002053 if err := dh.clearUNIData(ctx, &onu); err != nil {
2054 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302055 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002056 "onu-device": onu,
2057 "error": err})
2058 }
2059 // Clear flowids for gem cache.
2060 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002061 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002062 }
2063 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002064 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002065 if err != nil {
2066 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002067 "interface-id": intfID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002068 "onu-device": onu,
2069 "onu-gem": onuGemData,
2070 "error": err})
2071 //Not returning error on cleanup.
2072 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002073 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
2074 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002075 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002076 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002077 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002078 }
2079 }
2080 dh.onus.Delete(onuKey)
2081 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2082 return nil
2083}
Girish Gowdracefae192020-03-19 18:14:10 -07002084
2085func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2086 for _, field := range flows.GetOfbFields(flow) {
2087 if field.Type == flows.IN_PORT {
2088 return field.GetPort()
2089 }
2090 }
2091 return InvalidPort
2092}
2093
2094func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2095 for _, action := range flows.GetActions(flow) {
2096 if action.Type == flows.OUTPUT {
2097 if out := action.GetOutput(); out != nil {
2098 return out.GetPort()
2099 }
2100 }
2101 }
2102 return InvalidPort
2103}
2104
2105func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2106 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302107 logger.Debugw("increment-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002108 if inPort != InvalidPort && outPort != InvalidPort {
2109 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2110 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302111 logger.Debugw("increment-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002112
2113 dh.lockDevice.Lock()
2114 defer dh.lockDevice.Unlock()
2115 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2116 if !ok {
2117 flowRemoveData = pendingFlowRemoveData{
2118 pendingFlowRemoveCount: 0,
2119 allFlowsRemoved: make(chan struct{}),
2120 }
2121 }
2122 flowRemoveData.pendingFlowRemoveCount++
2123 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2124
Shrey Baid807a2a02020-04-09 12:52:45 +05302125 logger.Debugw("current-flow-remove-count–increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002126 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2127 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2128 }
2129}
2130
2131func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2132 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302133 logger.Debugw("decrement-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002134 if inPort != InvalidPort && outPort != InvalidPort {
2135 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2136 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302137 logger.Debugw("decrement-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002138
2139 dh.lockDevice.Lock()
2140 defer dh.lockDevice.Unlock()
2141 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302142 logger.Fatalf("flow-remove-key-not-found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002143 } else {
2144 if val.pendingFlowRemoveCount > 0 {
2145 val.pendingFlowRemoveCount--
2146 }
Shrey Baid807a2a02020-04-09 12:52:45 +05302147 logger.Debugw("current-flow-remove-count-after-decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002148 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2149 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2150 // If all flow removes have finished, then close the channel to signal the receiver
2151 // to go ahead with flow adds.
2152 if val.pendingFlowRemoveCount == 0 {
2153 close(val.allFlowsRemoved)
2154 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2155 return
2156 }
2157 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2158 }
2159 }
2160}
2161
2162func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2163 var flowRemoveData pendingFlowRemoveData
2164 var ok bool
2165 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302166 logger.Debugw("wait-for-flow-remove-to-finish-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002167 if inPort != InvalidPort && outPort != InvalidPort {
2168 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2169 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302170 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 -07002171
2172 dh.lockDevice.RLock()
2173 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302174 logger.Debugw("no-pending-flow-to-remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002175 dh.lockDevice.RUnlock()
2176 return
2177 }
2178 dh.lockDevice.RUnlock()
2179
2180 // Wait for all flow removes to finish first
2181 <-flowRemoveData.allFlowsRemoved
2182
Shrey Baid807a2a02020-04-09 12:52:45 +05302183 logger.Debugw("all-flows-cleared--handling-flow-add-now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002184 }
2185}
2186
2187func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2188 inPort := getInPortFromFlow(flow)
2189 outPort := getOutPortFromFlow(flow)
2190
2191 if inPort == InvalidPort || outPort == InvalidPort {
2192 return inPort, outPort
2193 }
2194
2195 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2196 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2197 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2198 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2199 return uniPort, outPort
2200 }
2201 }
2202 } else {
2203 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2204 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2205 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2206 return inPort, uniPort
2207 }
2208 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2209 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2210 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2211 return uniPort, outPort
2212 }
2213 }
2214 }
2215
2216 return InvalidPort, InvalidPort
2217}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002218
2219func extractOmciTransactionID(omciPkt []byte) uint16 {
2220 if len(omciPkt) > 3 {
2221 d := omciPkt[0:2]
2222 transid := binary.BigEndian.Uint16(d)
2223 return transid
2224 }
2225 return 0
2226}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002227
2228// StoreOnuDevice stores the onu parameters to the local cache.
2229func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2230 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2231 dh.onus.Store(onuKey, onuDevice)
2232}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002233
Devmalya Paula1efa642020-04-20 01:36:43 -04002234// setOnuITUPonAlarmConfig sets the parameters in the openolt agent for raising the ONU ITU PON alarms.
2235func (dh *DeviceHandler) setOnuITUPonAlarmConfig(config *oop.OnuItuPonAlarm) error {
2236 if _, err := dh.Client.OnuItuPonAlarmSet(context.Background(), config); err != nil {
2237 return err
2238 }
2239 logger.Debugw("onu-itu-pon-alarm-config-set-successful", log.Fields{"config": config})
2240 return nil
2241}
2242
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002243func (dh *DeviceHandler) getExtValue(device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
2244 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002245 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002246 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002247 resp := new(voltha.ReturnValues)
2248 valueparam := new(oop.ValueParam)
2249 ctx := context.Background()
2250 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002251 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2252 return nil, err
2253 }
2254 ID = device.ProxyAddress.GetOnuId()
2255 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2256 valueparam.Onu = &Onu
2257 valueparam.Value = value
2258
2259 // This API is unsupported until agent patch is added
2260 resp.Unsupported = uint32(value)
2261 _ = ctx
2262
2263 // Uncomment this code once agent changes are complete and tests
2264 /*
2265 resp, err = dh.Client.GetValue(ctx, valueparam)
2266 if err != nil {
2267 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2268 return nil, err
2269 }
2270 */
2271
2272 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2273 return resp, nil
2274}