blob: 04af0549485c3b7ac8de7bf891c084bef2ffe113 [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 Jeanneret1359c732019-08-01 21:40:02 -040022 "encoding/hex"
cuilin20187b2a8c32019-03-26 19:52:28 -070023 "fmt"
Girish Gowdracefae192020-03-19 18:14:10 -070024 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
cuilin20187b2a8c32019-03-26 19:52:28 -070025 "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
Chaitrashree G Sb2b62dd2019-07-24 21:47:04 -040032 "google.golang.org/grpc/codes"
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"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040048 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053049)
50
salmansiddiqui7ac62132019-08-22 03:58:50 +000051// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040052const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000053 MaxRetry = 10
54 MaxTimeOutInMs = 500
Girish Gowdracefae192020-03-19 18:14:10 -070055 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040056)
57
Girish Gowdracefae192020-03-19 18:14:10 -070058// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
59type pendingFlowRemoveDataKey struct {
60 intfID uint32
61 onuID uint32
62 uniID uint32
63}
64
65// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
66// This holds the number of pending flow removes and also a signal channel to
67// to indicate the receiver when all flow removes are handled
68type pendingFlowRemoveData struct {
69 pendingFlowRemoveCount uint32
70 allFlowsRemoved chan struct{}
71}
72
Phaneendra Manda4c62c802019-03-06 21:37:49 +053073//DeviceHandler will interact with the OLT device.
74type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070076 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040077 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070078 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053079 coreProxy adapterif.CoreProxy
80 AdapterProxy adapterif.AdapterProxy
81 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070082 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070083 exitChannel chan int
84 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053085 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070086 transitionMap *TransitionMap
87 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053088 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040089 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053090 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053091
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +053092 discOnus sync.Map
93 onus sync.Map
94 portStats *OpenOltStatisticsMgr
95 metrics *pmmetrics.PmMetrics
96 stopCollector chan bool
97 stopHeartbeatCheck chan bool
Chaitrashree G Sef088112020-02-03 21:39:27 -050098 activePorts sync.Map
Chaitrashree G Sa4649252020-03-11 21:24:11 -040099 stopIndications chan bool
Girish Gowdracefae192020-03-19 18:14:10 -0700100
101 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
102 // subscriber basis for the number of pending flow removes. This data is used
103 // to process all the flow removes for a subscriber before handling flow adds.
104 // Interleaving flow delete and flow add processing has known to cause PON resource
105 // management contentions on a per subscriber bases, so we need ensure ordering.
106 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107}
108
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700112 deviceType string
113 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 onuID uint32
115 intfID uint32
116 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +0000117 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530118 losRaised 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)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700153 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700154 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400155 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700156 dh.device = cloned
157 dh.openOLT = adapter
158 dh.exitChannel = make(chan int, 1)
159 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530160 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530161 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530162 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 -0500163 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400164 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700165 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
166
cuilin20187b2a8c32019-03-26 19:52:28 -0700167 //TODO initialize the support classes.
168 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530169}
170
171// start save the device to the data model
172func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700173 dh.lockDevice.Lock()
174 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000175 logger.Debugw("starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700176 // Add the initial device to the local model
Girish Kumar2ad402b2020-03-20 19:45:12 +0000177 logger.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530178}
179
180// stop stops the device dh. Not much to do for now
181func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700182 dh.lockDevice.Lock()
183 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000184 logger.Debug("stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700185 dh.exitChannel <- 1
Girish Kumar2ad402b2020-03-20 19:45:12 +0000186 logger.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530187}
188
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400189func macifyIP(ip net.IP) string {
190 if len(ip) > 0 {
191 oct1 := strconv.FormatInt(int64(ip[12]), 16)
192 oct2 := strconv.FormatInt(int64(ip[13]), 16)
193 oct3 := strconv.FormatInt(int64(ip[14]), 16)
194 oct4 := strconv.FormatInt(int64(ip[15]), 16)
195 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
196 }
197 return ""
198}
199
200func generateMacFromHost(host string) (string, error) {
201 var genmac string
202 var addr net.IP
203 var ips []string
204 var err error
205
Girish Kumar2ad402b2020-03-20 19:45:12 +0000206 logger.Debugw("generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400207
208 if addr = net.ParseIP(host); addr == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000209 logger.Debugw("looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400210
211 if ips, err = net.LookupHost(host); err == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000212 logger.Debugw("dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400213 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000214 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400215 }
216 genmac = macifyIP(addr)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000217 logger.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400218 return genmac, nil
219 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000220 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400221 }
222
223 genmac = macifyIP(addr)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000224 logger.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400225 return genmac, nil
226}
227
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530228func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700229 slist := strings.Split(mac, ":")
230 result := make([]uint32, len(slist))
231 var err error
232 var tmp int64
233 for index, val := range slist {
234 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
235 return []uint32{1, 2, 3, 4, 5, 6}
236 }
237 result[index] = uint32(tmp)
238 }
239 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530240}
241
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700242//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 -0800243func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530244
David K. Bainbridge794735f2020-02-11 21:01:37 -0800245 switch portType {
246 case voltha.Port_ETHERNET_NNI:
247 return fmt.Sprintf("nni-%d", portNum), nil
248 case voltha.Port_PON_OLT:
249 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700250 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800251
Girish Kumarf26e4882020-03-05 06:49:10 +0000252 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530253}
254
David K. Bainbridge794735f2020-02-11 21:01:37 -0800255func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000256 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700257 if state == "up" {
258 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500259 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500260 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700261 } else {
262 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500263 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700264 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700265 portNum := IntfIDToPortNo(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800266 label, err := GetportLabel(portNum, portType)
267 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000268 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400269 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500270
271 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
272 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000273 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500274 }
275 if device.Ports != nil {
276 for _, dPort := range device.Ports {
277 if dPort.Type == portType && dPort.PortNo == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000278 logger.Debug("port-already-exists-updating-oper-status-of-port")
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500279 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530280 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800281 "device-id": dh.device.Id,
282 "port-type": portType,
283 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000284 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800285
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500286 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800287 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500288 }
289 }
290 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400291 // Now create Port
292 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700293 PortNo: portNum,
294 Label: label,
295 Type: portType,
296 OperStatus: operStatus,
297 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000298 logger.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700299 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700300 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000301 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800302 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000303 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400304 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800305 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530306}
307
308// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800309func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000310 defer logger.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700311 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700312 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700313 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700314 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400315 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530316 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400317 if err != nil || device == nil {
318 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000319 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400320 }
321 // When the device is in DISABLED and Adapter container restarts, we need to
322 // rebuild the locally maintained admin state.
323 if device.AdminState == voltha.AdminState_DISABLED {
324 dh.lockDevice.Lock()
325 dh.adminState = "down"
326 dh.lockDevice.Unlock()
327 }
328
David Bainbridgef5879ca2019-12-13 21:17:54 +0000329 // Create an exponential backoff around re-enabling indications. The
330 // maximum elapsed time for the back off is set to 0 so that we will
331 // continue to retry. The max interval defaults to 1m, but is set
332 // here for code clarity
333 indicationBackoff := backoff.NewExponentialBackOff()
334 indicationBackoff.MaxElapsedTime = 0
335 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700336
337Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700338 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400339 select {
340 case <-dh.stopIndications:
Girish Kumar2ad402b2020-03-20 19:45:12 +0000341 logger.Debugw("Stopping-collecting-indications-for-OLT", log.Fields{"deviceID:": dh.deviceID})
Girish Gowdra3f974912020-03-23 20:35:18 -0700342 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400343 default:
344 indication, err := indications.Recv()
345 if err == io.EOF {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000346 logger.Infow("EOF for indications", log.Fields{"err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400347 // Use an exponential back off to prevent getting into a tight loop
348 duration := indicationBackoff.NextBackOff()
349 if duration == backoff.Stop {
350 // If we reach a maximum then warn and reset the backoff
351 // timer and keep attempting.
Girish Kumar2ad402b2020-03-20 19:45:12 +0000352 logger.Warnw("Maximum indication backoff reached, resetting backoff timer",
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400353 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
354 indicationBackoff.Reset()
355 }
356 time.Sleep(indicationBackoff.NextBackOff())
Girish Gowdra3f974912020-03-23 20:35:18 -0700357 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
358 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400359 }
360 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000361 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530362 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700363 logger.Errorw("Read indication error", log.Fields{"err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400364 if dh.adminState == "deleted" {
Girish Gowdra3f974912020-03-23 20:35:18 -0700365 logger.Debug("Device deleted stopping the read indication thread")
366 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400367 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700368 // Close the stream, and re-initialize it
369 if err = indications.CloseSend(); err != nil {
370 // Ok to ignore here, because we landed here due to a problem on the stream
371 // In all probability, the closeSend call may fail
372 logger.Debugw("error closing send stream, error ignored", log.Fields{"err": err})
373 }
374 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
375 return err
376 }
377 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400378 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530379 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400380 // Reset backoff if we have a successful receive
381 indicationBackoff.Reset()
382 dh.lockDevice.RLock()
383 adminState := dh.adminState
384 dh.lockDevice.RUnlock()
385 // When OLT is admin down, ignore all indications.
386 if adminState == "down" && !isIndicationAllowedDuringOltAdminDown(indication) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000387 logger.Debugw("olt is admin down, ignore indication", log.Fields{"indication": indication})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400388 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400389 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400390 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700391 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700392 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700393 // Close the send stream
394 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
395 return nil
396}
397
398func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
399
400 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
401 if err != nil {
402 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
403 }
404 if indications == nil {
405 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
406 }
407
408 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400409}
410
411// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
412func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
413 switch indication.Data.(type) {
414 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
415 return true
416
417 default:
418 return false
419 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700420}
421
David K. Bainbridge794735f2020-02-11 21:01:37 -0800422func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000423 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000424 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530425 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700426 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530427 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700428 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000429 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800430 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530431 return olterrors.NewErrAdapter("failed-indication", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800432 "device_id": dh.deviceID,
433 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000434 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800435 }
436 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700437}
438
David K. Bainbridge794735f2020-02-11 21:01:37 -0800439// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530440func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400441 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700442 switch indication.Data.(type) {
443 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800444 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530445 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800446 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700447 case *oop.Indication_IntfInd:
448 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800449 go func() {
450 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530451 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800452 }
453 }()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000454 logger.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700455 case *oop.Indication_IntfOperInd:
456 intfOperInd := indication.GetIntfOperInd()
457 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800458 go func() {
459 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530460 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800461 }
462 }()
npujarec5762e2020-01-01 14:08:48 +0530463 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700464 } else if intfOperInd.GetType() == "pon" {
465 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
466 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800467 go func() {
468 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530469 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800470 }
471 }()
kesavand39e0aa32020-01-28 20:58:50 -0500472 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700473 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000474 logger.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700475 case *oop.Indication_OnuDiscInd:
476 onuDiscInd := indication.GetOnuDiscInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000477 logger.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700478 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800479 go func() {
480 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530481 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800482 }
483 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700484 case *oop.Indication_OnuInd:
485 onuInd := indication.GetOnuInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000486 logger.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487 go func() {
488 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530489 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800490 }
491 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700492 case *oop.Indication_OmciInd:
493 omciInd := indication.GetOmciInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000494 logger.Debugw("Received Omci indication ", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "pkt": hex.EncodeToString(omciInd.Pkt)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800495 go func() {
496 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530497 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800498 }
499 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700500 case *oop.Indication_PktInd:
501 pktInd := indication.GetPktInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000502 logger.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800503 go func() {
504 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530505 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800506 }
507 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700508 case *oop.Indication_PortStats:
509 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530510 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700511 case *oop.Indication_FlowStats:
512 flowStats := indication.GetFlowStats()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000513 logger.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700514 case *oop.Indication_AlarmInd:
515 alarmInd := indication.GetAlarmInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000516 logger.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530517 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700518 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530519}
520
521// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530522func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400523 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530524 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400525 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000526 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400527 }
528 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530529}
530
531// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530532func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700533 dh.lockDevice.Lock()
534 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000535 logger.Debug("do-state-down-start")
Girish Gowdrud4245152019-05-10 00:47:31 -0400536
npujarec5762e2020-01-01 14:08:48 +0530537 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400538 if err != nil || device == nil {
539 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000540 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400541 }
542
543 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400544
545 //Update the device oper state and connection status
546 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400547 dh.device = cloned
548
David K. Bainbridge794735f2020-02-11 21:01:37 -0800549 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000550 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400551 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400552
553 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530554 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400555 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000556 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400557 }
558 for _, onuDevice := range onuDevices.Items {
559
560 // Update onu state as down in onu adapter
561 onuInd := oop.OnuIndication{}
562 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800563 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700564 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800565 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530566 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800567 "source": "openolt",
568 "onu-indicator": onuInd,
569 "device-type": onuDevice.Type,
570 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700571 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700572 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400573 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700574 /* Discovered ONUs entries need to be cleared , since after OLT
575 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530576 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000577 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700578 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530579}
580
581// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530582func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400583 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800584 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530585 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800586 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000587 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400588 }
589 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530590}
591
592// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530593func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400594 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530595 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400596 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530597}
598
599// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530600func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000601 logger.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400602
603 // Case where OLT is disabled and then rebooted.
604 if dh.adminState == "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000605 logger.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530606 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400607 if err != nil || device == nil {
608 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530609 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400610 }
611
612 cloned := proto.Clone(device).(*voltha.Device)
613 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
614 cloned.OperStatus = voltha.OperStatus_UNKNOWN
615 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530616 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530617 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400618 }
619
Chaitrashree G S44124192019-08-07 20:21:36 -0400620 // 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 +0530621 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400622 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530623 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400624 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400625 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
626 // all the modules initialized and ready to handle incoming ONUs.
627
628 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
629 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
630 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400631
632 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800633 go func() {
634 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530635 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800636 }
637 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400638 return nil
639 }
640
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700641 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400642 if err != nil || device == nil {
643 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000644 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400645 }
kesavand39e0aa32020-01-28 20:58:50 -0500646 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500647 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000648 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400649 }
650
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400651 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
652 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400653 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530654
cuilin20187b2a8c32019-03-26 19:52:28 -0700655 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800656 go func() {
657 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530658 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800659 }
660 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700661 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530662}
663
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400664func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
665 deviceInfo, err := dh.populateDeviceInfo()
666
667 if err != nil {
668 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
669 }
670 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
671 // Instantiate resource manager
672 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
673 return olterrors.ErrResourceManagerInstantiating
674 }
675
676 // Instantiate flow manager
677 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
678 return olterrors.ErrResourceManagerInstantiating
679
680 }
681 /* TODO: Instantiate Alarm , stats , BW managers */
682 /* Instantiating Event Manager to handle Alarms and KPIs */
683 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
684
685 // Stats config for new device
686 dh.portStats = NewOpenOltStatsMgr(dh)
687
688 return nil
689
690}
691
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400692func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
693 var err error
694 var deviceInfo *oop.DeviceInfo
695
696 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
697
698 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000699 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400700 }
701 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000702 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400703 }
704
Girish Kumar2ad402b2020-03-20 19:45:12 +0000705 logger.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400706 dh.device.Root = true
707 dh.device.Vendor = deviceInfo.Vendor
708 dh.device.Model = deviceInfo.Model
709 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
710 dh.device.HardwareVersion = deviceInfo.HardwareVersion
711 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
712
713 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000714 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400715 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
716 genmac, err := generateMacFromHost(host)
717 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000718 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400719 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000720 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400721 dh.device.MacAddress = genmac
722 } else {
723 dh.device.MacAddress = deviceInfo.DeviceId
724 }
725
726 // Synchronous call to update device - this method is run in its own go routine
727 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000728 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400729 }
730
731 return deviceInfo, nil
732}
733
Naga Manjunath7615e552019-10-11 22:35:47 +0530734func startCollector(dh *DeviceHandler) {
735 // Initial delay for OLT initialization
736 time.Sleep(1 * time.Minute)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000737 logger.Debugf("Starting-Collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530738 context := make(map[string]string)
739 for {
740 select {
741 case <-dh.stopCollector:
Girish Kumar2ad402b2020-03-20 19:45:12 +0000742 logger.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
Naga Manjunath7615e552019-10-11 22:35:47 +0530743 return
744 default:
745 freq := dh.metrics.ToPmConfigs().DefaultFreq
746 time.Sleep(time.Duration(freq) * time.Second)
747 context["oltid"] = dh.deviceID
748 context["devicetype"] = dh.deviceType
749 // NNI Stats
750 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
Girish Kumar2ad402b2020-03-20 19:45:12 +0000751 logger.Debugf("Collect-NNI-Metrics %v", cmnni)
Naga Manjunath7615e552019-10-11 22:35:47 +0530752 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000753 logger.Debugf("Publish-NNI-Metrics")
Naga Manjunath7615e552019-10-11 22:35:47 +0530754 // PON Stats
755 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500756 for i := uint32(0); i < NumPonPORTS; i++ {
757 if val, ok := dh.activePorts.Load(i); ok && val == true {
758 cmpon := dh.portStats.collectPONMetrics(i)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000759 logger.Debugf("Collect-PON-Metrics %v", cmpon)
Naga Manjunath7615e552019-10-11 22:35:47 +0530760
Chaitrashree G Sef088112020-02-03 21:39:27 -0500761 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000762 logger.Debugf("Publish-PON-Metrics")
Chaitrashree G Sef088112020-02-03 21:39:27 -0500763 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530764 }
765 }
766 }
767}
768
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700769//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530770func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400771 dh.transitionMap = NewTransitionMap(dh)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000772 logger.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530773 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530774
775 // Now, set the initial PM configuration for that device
776 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530777 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530778 }
779
780 go startCollector(dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400781 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530782}
783
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700784//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530785func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700786 return &ic.SwitchCapability{
787 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530788 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700789 HwDesc: "open_pon",
790 SwDesc: "open_pon",
791 SerialNum: dh.device.SerialNumber,
792 },
793 SwitchFeatures: &of.OfpSwitchFeatures{
794 NBuffers: 256,
795 NTables: 2,
796 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
797 of.OfpCapabilities_OFPC_TABLE_STATS |
798 of.OfpCapabilities_OFPC_PORT_STATS |
799 of.OfpCapabilities_OFPC_GROUP_STATS),
800 },
801 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530802}
803
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700804//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530805func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700806 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700807 return &ic.PortCapability{
808 Port: &voltha.LogicalPort{
809 OfpPort: &of.OfpPort{
810 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
811 Config: 0,
812 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700813 Curr: capacity,
814 Advertised: capacity,
815 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700816 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
817 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
818 },
819 DeviceId: dh.device.Id,
820 DevicePortNo: uint32(portNo),
821 },
822 }, nil
823}
824
David K. Bainbridge794735f2020-02-11 21:01:37 -0800825func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000826 logger.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700827 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700828 var deviceID string
829 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700830
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700831 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530832
833 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
834
Girish Kumar2ad402b2020-03-20 19:45:12 +0000835 logger.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700836 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700837 kwargs := make(map[string]interface{})
838 kwargs["onu_id"] = omciInd.OnuId
839 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700840
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700841 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
842 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530843 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800844 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000845 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700846 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 deviceType = onuDevice.Type
848 deviceID = onuDevice.Id
849 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
850 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530851 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700852 } else {
853 //found in cache
Girish Kumar2ad402b2020-03-20 19:45:12 +0000854 logger.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530855 deviceType = onuInCache.(*OnuDevice).deviceType
856 deviceID = onuInCache.(*OnuDevice).deviceID
857 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700858 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700859
860 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800861 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700862 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800863 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530864 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800865 "source": dh.deviceType,
866 "destination": deviceType,
867 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000868 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700869 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800870 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530871}
872
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700873//ProcessInterAdapterMessage sends the proxied messages to the target device
874// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
875// is meant, and then send the unmarshalled omci message to this onu
876func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000877 logger.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700878 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700879 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700880 fromTopic := msg.Header.FromTopic
881 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700882 toDeviceID := msg.Header.ToDeviceId
883 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700884
Girish Kumar2ad402b2020-03-20 19:45:12 +0000885 logger.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700886
887 msgBody := msg.GetBody()
888
889 omciMsg := &ic.InterAdapterOmciMessage{}
890 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000891 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700892 }
893
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700894 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700895 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
896 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530897 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800898 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000899 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700900 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000901 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 -0800902 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530903 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800904 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000905 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800906 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700907 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000908 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 -0800909 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530910 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800911 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000912 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800913 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700914 }
915
916 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000917 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700918 }
919 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530920}
921
David K. Bainbridge794735f2020-02-11 21:01:37 -0800922func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700923 var intfID uint32
924 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000925 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700926 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700927 intfID = onuDevice.ProxyAddress.GetChannelId()
928 onuID = onuDevice.ProxyAddress.GetOnuId()
929 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700930 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700931 intfID = omciMsg.GetProxyAddress().GetChannelId()
932 onuID = omciMsg.GetProxyAddress().GetOnuId()
933 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700934 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700935 if connectStatus != voltha.ConnectStatus_REACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000936 logger.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800937
Thomas Lee S94109f12020-03-03 16:39:29 +0530938 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800939 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000940 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700941 }
942
lcuie24ef182019-04-29 22:58:36 -0700943 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
944 isHexString := false
945 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
946 if decodeerr == nil {
947 isHexString = true
948 }
949
950 // TODO: OpenOLT Agent expects a hex string for OMCI packets rather than binary. Fix this in the agent and then we can pass binary Pkt: omciMsg.Message.
951 var omciMessage *oop.OmciMsg
952 if isHexString {
953 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
954 } else {
955 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
956 hex.Encode(hexPkt, omciMsg.Message)
957 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
958 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700959
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700960 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
961 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530962 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800963 "interface-id": intfID,
964 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000965 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700966 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000967 logger.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800968 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700969}
970
David K. Bainbridge794735f2020-02-11 21:01:37 -0800971func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000972 logger.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
npujarec5762e2020-01-01 14:08:48 +0530973 dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700974 // TODO: need resource manager
975 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530977 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400978 st, _ := status.FromError(err)
979 if st.Code() == codes.AlreadyExists {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000980 logger.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400981 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000982 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400983 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700984 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000985 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
cuilin20187b2a8c32019-03-26 19:52:28 -0700986 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800987 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700988}
989
David K. Bainbridge794735f2020-02-11 21:01:37 -0800990func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -0800991
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700992 channelID := onuDiscInd.GetIntfId()
993 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -0400994
Girish Kumar2ad402b2020-03-20 19:45:12 +0000995 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530996
cuilin20187b2a8c32019-03-26 19:52:28 -0700997 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400998 if sn != "" {
999 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001000 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001001 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001002 }
1003
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301004 var alarmInd oop.OnuAlarmIndication
1005 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001006 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301007
1008 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1009 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1010 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1011 OnuLosRaise event sent for it */
1012 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1013 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1014 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001015 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301016 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1017 "currentIntfId": onuDiscInd.GetIntfId()})
1018 // TODO:: Should we need to ignore raising OnuLosClear event
1019 // when onu connected to different PON?
1020 }
1021 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1022 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1023 alarmInd.LosStatus = statusCheckOff
1024 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1025 }
1026 return true
1027 })
1028
Girish Kumar2ad402b2020-03-20 19:45:12 +00001029 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001030 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001031 }
1032
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001033 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001034
1035 // check the ONU is already know to the OLT
1036 // NOTE the second time the ONU is discovered this should return a device
1037 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1038
1039 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001040 logger.Warnw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001041 if e, ok := status.FromError(err); ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001042 logger.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001043 switch e.Code() {
1044 case codes.Internal:
1045 // this probably means NOT FOUND, so just create a new device
1046 onuDevice = nil
1047 case codes.DeadlineExceeded:
1048 // if the call times out, cleanup and exit
1049 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001050 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001051 }
1052 }
1053 }
1054
1055 if onuDevice == nil {
1056 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Girish Kumar2ad402b2020-03-20 19:45:12 +00001057 logger.Infow("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001058 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001059 ponintfid := onuDiscInd.GetIntfId()
1060 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301061 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001062 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001063
Girish Kumar2ad402b2020-03-20 19:45:12 +00001064 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001065
1066 if err != nil {
1067 // if we can't create an ID in resource manager,
1068 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001069 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001070 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001071 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001072 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001073 }
1074
1075 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1076 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001077 dh.discOnus.Delete(sn)
1078 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 +05301079 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001080 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001081 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001082 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001083 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Girish Kumar2ad402b2020-03-20 19:45:12 +00001084 logger.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001085 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001086
1087 // we can now use the existing ONU Id
1088 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001089 //Insert the ONU into cache to use in OnuIndication.
1090 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001091 logger.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
Matteo Scandolo945e4012019-12-12 14:16:11 -08001092 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001093 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001094
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301095 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301096 dh.onus.Store(onuKey, onuDev)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001097 logger.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001098
David K. Bainbridge794735f2020-02-11 21:01:37 -08001099 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301100 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001101 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001102 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001103 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001104 logger.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001105 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301106 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001108 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001109 }
1110 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001111}
1112
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001114 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1115
1116 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001117 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001118 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001119 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001120 foundInCache := false
Girish Kumar2ad402b2020-03-20 19:45:12 +00001121 logger.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
Scott Baker7eb0a932019-07-26 10:33:22 -07001122 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001123 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301124
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 errFields := log.Fields{"device-id": dh.device.Id}
1126
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301127 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1128
Mahir Gunyele77977b2019-06-27 05:36:22 -07001129 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1130 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001131 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1132 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001133 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001134 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1135 if serialNumber != "" {
1136 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001137 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001138 } else {
1139 kwargs["onu_id"] = onuInd.OnuId
1140 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001141 errFields["onu-id"] = onuInd.OnuId
1142 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001143 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001145 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001146
David K. Bainbridge794735f2020-02-11 21:01:37 -08001147 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001148 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001149 }
1150
David K. Bainbridge794735f2020-02-11 21:01:37 -08001151 if onuDevice.ParentPortNo != ponPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001152 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 "previousIntfId": onuDevice.ParentPortNo,
1154 "currentIntfId": ponPort})
1155 }
1156
1157 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001158 logger.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1160 "received_onu_id": onuInd.OnuId})
1161 }
1162 if !foundInCache {
1163 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1164
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301165 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 -08001166
1167 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001168 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001169 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 }
1171 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001172}
1173
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001174func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301175 ctx := context.TODO()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001176 logger.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001177 if onuInd.AdminState == "down" {
1178 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1179 if onuInd.OperState != "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001180 logger.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001181 onuInd.OperState = "down"
1182 }
1183 }
1184
David K. Bainbridge794735f2020-02-11 21:01:37 -08001185 switch onuInd.OperState {
1186 case "down":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001187 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001188 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301189 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001190 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1191 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301192 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 "onu-indicator": onuInd,
1194 "source": "openolt",
1195 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001196 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001197 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001198 case "up":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001199 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Matt Jeanneret53539512019-07-20 14:47:02 -04001200 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301201 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001202 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1203 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301204 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001205 "onu-indicator": onuInd,
1206 "source": "openolt",
1207 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001208 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001209 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001211 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001212 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001213 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001214}
1215
cuilin20187b2a8c32019-03-26 19:52:28 -07001216func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1217 if serialNum != nil {
1218 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001219 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001220 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001221}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001222func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1223 decodedStr, err := hex.DecodeString(serialNum[4:])
1224 if err != nil {
1225 return nil, err
1226 }
1227 return &oop.SerialNumber{
1228 VendorId: []byte(serialNum[:4]),
1229 VendorSpecific: []byte(decodedStr),
1230 }, nil
1231}
cuilin20187b2a8c32019-03-26 19:52:28 -07001232
1233func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1234 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001235 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001236 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1237 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1238 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1239 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1240 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1241 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1242 return tmp
1243}
1244
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001245//UpdateFlowsBulk upates the bulk flow
1246func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301247 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001248}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001249
1250//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001252 logger.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001253 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001254 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001255 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001256 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001257 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001258 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001259 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001260 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001261 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001262 logger.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301264}
1265
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001266// SendPacketInToCore sends packet-in to core
1267// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1268// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001269func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001270 logger.Debugw("send-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001271 "port": logicalPort,
1272 "packet": hex.EncodeToString(packetPayload),
1273 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001274 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301275 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001276 "source": "adapter",
1277 "destination": "core",
1278 "device-id": dh.device.Id,
1279 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001280 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001281 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001282 logger.Debugw("Sent packet-in to core successfully", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001283 "packet": hex.EncodeToString(packetPayload),
1284 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001285 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001286}
1287
A R Karthick1f85b802019-10-11 05:06:05 +00001288// AddUniPortToOnu adds the uni port to the onu device
1289func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1290 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301291
1292 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001293 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301294 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1295 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001296 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001297 }
1298 }
1299}
1300
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001301//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301302func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001303 logger.Debugw("Received-incremental-flowupdate-in-device-handler", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001304
1305 var errorsList []error
1306
Girish Gowdru0c588b22019-04-23 23:24:56 -04001307 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001308 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001309 dh.incrementActiveFlowRemoveCount(flow)
1310
Girish Kumar2ad402b2020-03-20 19:45:12 +00001311 logger.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001312 err := dh.flowMgr.RemoveFlow(ctx, flow)
1313 if err != nil {
1314 errorsList = append(errorsList, err)
1315 }
1316
1317 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001318 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301319
1320 for _, flow := range flows.ToAdd.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001321 logger.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001322 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1323 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001324 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1325 if err != nil {
1326 errorsList = append(errorsList, err)
1327 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301328 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001329 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001330 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001331 for _, flow := range flows.ToRemove.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001332 logger.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001333 // dh.flowMgr.RemoveFlow(flow)
1334 }
1335 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001336
Girish Gowdracefae192020-03-19 18:14:10 -07001337 // 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 +00001338 if groups != nil {
1339 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001340 err := dh.flowMgr.AddGroup(ctx, group)
1341 if err != nil {
1342 errorsList = append(errorsList, err)
1343 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001344 }
1345 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001346 err := dh.flowMgr.ModifyGroup(ctx, group)
1347 if err != nil {
1348 errorsList = append(errorsList, err)
1349 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001350 }
1351 if len(groups.ToRemove.Items) != 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001352 logger.Debug("Group delete operation is not supported for now")
Esin Karamanccb714b2019-11-29 15:02:06 +00001353 }
1354 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001355 if len(errorsList) > 0 {
1356 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1357 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001358 logger.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001359 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301360}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001361
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001362//DisableDevice disables the given device
1363//It marks the following for the given device:
1364//Device-Handler Admin-State : down
1365//Device Port-State: UNKNOWN
1366//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001367func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001368 /* On device disable ,admin state update has to be done prior sending request to agent since
1369 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001370 dh.lockDevice.Lock()
1371 dh.adminState = "down"
1372 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001373 if dh.Client != nil {
1374 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1375 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001376 dh.lockDevice.Lock()
1377 dh.adminState = "up"
1378 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001379 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001380 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001381 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001382 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001383 logger.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001384 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001385 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301386
1387 dh.discOnus = sync.Map{}
1388 dh.onus = sync.Map{}
1389
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301390 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001391 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001392 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1393 for _, port := range cloned.Ports {
1394 if port.GetType() == voltha.Port_PON_OLT {
1395 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1396 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001397 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001398 }
1399 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001400 }
1401
Girish Kumar2ad402b2020-03-20 19:45:12 +00001402 logger.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001403 return nil
1404}
1405
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301406func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001407
1408 // Update onu state as unreachable in onu adapter
1409 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301410 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001411 //get the child device for the parent device
1412 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1413 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001414 logger.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001415 }
1416 if onuDevices != nil {
1417 for _, onuDevice := range onuDevices.Items {
1418 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1419 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1420 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001421 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001422 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1423 }
1424
1425 }
1426 }
1427
1428}
1429
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001430//ReenableDevice re-enables the olt device after disable
1431//It marks the following for the given device:
1432//Device-Handler Admin-State : up
1433//Device Port-State: ACTIVE
1434//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001435func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001436 dh.lockDevice.Lock()
1437 dh.adminState = "up"
1438 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301439
1440 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1441 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301442 dh.lockDevice.Lock()
1443 dh.adminState = "down"
1444 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001445 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301446 }
1447 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001448 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001449
1450 cloned := proto.Clone(device).(*voltha.Device)
1451 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001452
kdarapu1afeceb2020-02-12 01:38:09 -05001453 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001454 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001455 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001456 //Update the device oper status as ACTIVE
1457 cloned.OperStatus = voltha.OperStatus_ACTIVE
1458 dh.device = cloned
1459
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001460 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301461 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001462 "device-id": device.Id,
1463 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001464 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001465 }
kesavand39e0aa32020-01-28 20:58:50 -05001466
Girish Kumar2ad402b2020-03-20 19:45:12 +00001467 logger.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001468
1469 return nil
1470}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001471
npujarec5762e2020-01-01 14:08:48 +05301472func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001473 var uniID uint32
1474 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301475 for _, port := range onu.UniPorts {
1476 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001477 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001478 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301479 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001480 logger.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001481 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001482 logger.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301483 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001484 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301485 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001486 }
npujarec5762e2020-01-01 14:08:48 +05301487 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001488 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301489 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001490 logger.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001491 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001492 logger.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301493 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001494 logger.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001495 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001496 logger.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301497 }
npujarec5762e2020-01-01 14:08:48 +05301498 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1499 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001500 logger.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301501 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001502 logger.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301503 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001504 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 +00001505 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001506 }
1507 return nil
1508}
1509
npujarec5762e2020-01-01 14:08:48 +05301510func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001511 nniUniID := -1
1512 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301513
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001514 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001515 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001516 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001517 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301518 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301519 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001520 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001521 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001522 logger.Debugw("NNI are ", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301523 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301524 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001525 logger.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301526 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301527 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301528 }
npujarec5762e2020-01-01 14:08:48 +05301529 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001530 }
npujarec5762e2020-01-01 14:08:48 +05301531 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001532 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301533 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001534 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001535}
1536
1537// 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 +05301538func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001539 logger.Debug("Function entry delete device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001540 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001541 if dh.adminState == "deleted" {
1542 dh.lockDevice.Unlock()
1543 return nil
1544 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001545 dh.adminState = "deleted"
1546 dh.lockDevice.Unlock()
1547 /* Clear the KV store data associated with the all the UNI ports
1548 This clears up flow data and also resource map data for various
1549 other pon resources like alloc_id and gemport_id
1550 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001551 go dh.cleanupDeviceResources(ctx)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001552 logger.Debug("Removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001553 // Stop the Stats collector
1554 dh.stopCollector <- true
1555 // stop the heartbeat check routine
1556 dh.stopHeartbeatCheck <- true
1557 //Reset the state
1558 if dh.Client != nil {
1559 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
1560 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
1561 }
1562 }
1563 cloned := proto.Clone(device).(*voltha.Device)
1564 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1565 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1566 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1567 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1568 "device-id": device.Id,
1569 "connect-status": cloned.ConnectStatus,
1570 "oper-status": cloned.OperStatus}, err).Log()
1571 }
1572 return nil
1573}
1574func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001575 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301576 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1577 var ponPort uint32
1578 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1579 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301580 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301581 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301582 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001583 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001584 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301585 }
1586 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301587 onuID := make([]uint32, 1)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001588 logger.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301589 if err = dh.clearUNIData(ctx, &onu); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001590 logger.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301591 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301592 // Clear flowids for gem cache.
1593 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301594 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301595 }
1596 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301597 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301598 }
npujarec5762e2020-01-01 14:08:48 +05301599 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301600 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301601 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301602 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001603 logger.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001604 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001605 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001606 /* Clear the flows from KV store associated with NNI port.
1607 There are mostly trap rules from NNI port (like LLDP)
1608 */
npujarec5762e2020-01-01 14:08:48 +05301609 if err := dh.clearNNIData(ctx); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001610 logger.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001611 }
A R Karthick1f85b802019-10-11 05:06:05 +00001612
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001613 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301614 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001615 }
A R Karthick1f85b802019-10-11 05:06:05 +00001616
Devmalya Paul495b94a2019-08-27 19:42:00 -04001617 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301618 dh.onus.Range(func(key interface{}, value interface{}) bool {
1619 dh.onus.Delete(key)
1620 return true
1621 })
1622
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001623 /*Delete discovered ONU map for the device*/
1624 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1625 dh.discOnus.Delete(key)
1626 return true
1627 })
1628
Devmalya Paul495b94a2019-08-27 19:42:00 -04001629 return nil
1630}
1631
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001632//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001633func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1634 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001635 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001636 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001637 logger.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001638 return nil
1639}
1640
David K. Bainbridge794735f2020-02-11 21:01:37 -08001641func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001642 logger.Debugw("Received packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001643 "packet-indication": *packetIn,
1644 "packet": hex.EncodeToString(packetIn.Pkt),
1645 })
npujarec5762e2020-01-01 14:08:48 +05301646 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001647 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001648 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001649 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001650 logger.Debugw("sending packet-in to core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001651 "logicalPortNum": logicalPortNum,
1652 "packet": hex.EncodeToString(packetIn.Pkt),
1653 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001654 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301655 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001656 "destination": "core",
1657 "source": dh.deviceType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001658 "packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001659 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001660 logger.Debugw("Success sending packet-in to core!", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001661 "packet": hex.EncodeToString(packetIn.Pkt),
1662 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001663 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001664}
1665
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001666// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301667func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001668 logger.Debugw("incoming-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001669 "deviceID": dh.deviceID,
1670 "egress_port_no": egressPortNo,
1671 "pkt-length": len(packet.Data),
1672 "packet": hex.EncodeToString(packet.Data),
1673 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001674
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001675 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001676 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001677 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1678 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301679 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1680 // Do not packet-out lldp packets on uni port.
1681 // ONOS has no clue about uni/nni ports, it just packets out on all
1682 // available ports on the Logical Switch. It should not be interested
1683 // in the UNI links.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001684 logger.Debug("dropping-lldp-packet-out-on-uni")
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301685 return nil
1686 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001687 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1688 if innerEthType == 0x8100 {
1689 // q-in-q 802.1ad or 802.1q double tagged packet.
1690 // slice out the outer tag.
1691 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001692 logger.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001693 }
1694 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001695 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1696 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001697 uniID := UniIDFromPortNum(uint32(egressPortNo))
1698
npujarec5762e2020-01-01 14:08:48 +05301699 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001700 if err != nil {
1701 // In this case the openolt agent will receive the gemPortID as 0.
1702 // The agent tries to retrieve the gemPortID in this case.
1703 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001704 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001705 "packet": hex.EncodeToString(packet.Data),
1706 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001707 }
1708
1709 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001710
Girish Kumar2ad402b2020-03-20 19:45:12 +00001711 logger.Debugw("sending-packet-to-onu", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001712 "egress_port_no": egressPortNo,
1713 "IntfId": intfID,
1714 "onuID": onuID,
1715 "uniID": uniID,
1716 "gemPortID": gemPortID,
1717 "packet": hex.EncodeToString(packet.Data),
1718 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001719
npujarec5762e2020-01-01 14:08:48 +05301720 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301721 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001722 "source": "adapter",
1723 "destination": "onu",
1724 "egress-port-number": egressPortNo,
1725 "interface-id": intfID,
1726 "oni-id": onuID,
1727 "uni-id": uniID,
1728 "gem-port-id": gemPortID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001729 "packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001730 }
1731 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001732 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1733 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001734 return olterrors.NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001735 }
1736 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001737
Girish Kumar2ad402b2020-03-20 19:45:12 +00001738 logger.Debugw("sending-packet-to-nni", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001739 "uplink_pkt": uplinkPkt,
1740 "packet": hex.EncodeToString(packet.Data),
1741 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001742
npujarec5762e2020-01-01 14:08:48 +05301743 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001744 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001745 }
1746 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001747 logger.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001748 "egress_port_no": egressPortNo,
1749 "egressPortType": egressPortType,
1750 "packet": hex.EncodeToString(packet.Data),
1751 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001752 }
1753 return nil
1754}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001755
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001756func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1757 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001758}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301759
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001760func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301761 // start the heartbeat check towards the OLT.
1762 var timerCheck *time.Timer
1763
1764 for {
1765 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1766 select {
1767 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001768 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1769 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001770 logger.Error("Hearbeat failed")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301771 if timerCheck == nil {
1772 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001773 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301774 }
1775 } else {
1776 if timerCheck != nil {
1777 if timerCheck.Stop() {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001778 logger.Debug("We got hearbeat within the timeout")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301779 }
1780 timerCheck = nil
1781 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001782 logger.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301783 }
1784 cancel()
1785 case <-dh.stopHeartbeatCheck:
Girish Kumar2ad402b2020-03-20 19:45:12 +00001786 logger.Debug("Stopping heart beat check")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301787 return
1788 }
1789 }
1790}
1791
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001792func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1793 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1794 if err != nil || device == nil {
1795 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1796 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301797
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001798 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1799 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1800 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1801 }
1802 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1803 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1804 }
1805 go dh.cleanupDeviceResources(ctx)
1806
1807 dh.stopIndications <- true
1808 dh.transitionMap.Handle(ctx, DeviceInit)
1809
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301810 }
1811}
kesavand39e0aa32020-01-28 20:58:50 -05001812
1813// EnablePort to enable Pon interface
1814func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001815 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001816 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001817}
1818
1819// DisablePort to disable pon interface
1820func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001821 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001822 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001823}
1824
kdarapu1afeceb2020-02-12 01:38:09 -05001825//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1826func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301827 ctx := context.Background()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001828 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001829 if port.GetType() == voltha.Port_ETHERNET_NNI {
1830 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001831 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
kesavand39e0aa32020-01-28 20:58:50 -05001832 log.Fields{"Device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301833 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001834 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001835 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001836 }
1837 // fetch interfaceid from PortNo
1838 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1839 ponIntf := &oop.Interface{IntfId: ponID}
1840 var operStatus voltha.OperStatus_Types
1841 if enablePort {
1842 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301843 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001844
1845 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301846 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001847 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001848 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001849 }
1850 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001851 dh.activePorts.Store(ponID, true)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001852 logger.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001853 } else {
1854 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301855 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001856 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301857 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001858 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001859 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001860 }
1861 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001862 dh.activePorts.Store(ponID, false)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001863 logger.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001864 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001865 if err := dh.coreProxy.PortStateUpdate(ctx, dh.deviceID, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301866 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001867 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001868 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001869 }
1870 return nil
1871}
1872
kdarapu1afeceb2020-02-12 01:38:09 -05001873//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1874func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001875 cloned := proto.Clone(device).(*voltha.Device)
1876 // Disable the port and update the oper_port_status to core
1877 // if the Admin state of the port is disabled on reboot and re-enable device.
1878 for _, port := range cloned.Ports {
1879 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001880 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301881 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001882 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001883 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001884 }
1885 }
1886 }
1887 return nil
1888}
1889
1890//populateActivePorts to populate activePorts map
1891func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001892 logger.Info("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001893 for _, port := range device.Ports {
1894 if port.Type == voltha.Port_ETHERNET_NNI {
1895 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001896 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001897 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001898 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001899 }
1900 }
1901 if port.Type == voltha.Port_PON_OLT {
1902 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001903 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001904 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001905 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001906 }
1907 }
1908 }
1909}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001910
1911// ChildDeviceLost deletes ONU and clears pon resources related to it.
1912func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001913 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001914 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1915 onuKey := dh.formOnuKey(IntfID, onuID)
1916 onuDevice, ok := dh.onus.Load(onuKey)
1917 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301918 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001919 log.Fields{
1920 "device-id": dh.deviceID,
1921 "onu-id": onuID,
1922 "interface-id": IntfID}, nil).Log()
1923 }
1924 var sn *oop.SerialNumber
1925 var err error
1926 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301927 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001928 log.Fields{
1929 "devicer-id": dh.deviceID,
1930 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1931 }
1932 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1933 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301934 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001935 "device-id": dh.deviceID,
1936 "onu-id": onuID}, err).Log()
1937 }
1938 //clear PON resources associated with ONU
1939 var onuGemData []rsrcMgr.OnuGemInfo
1940 if err := dh.resourceMgr.ResourceMgrs[IntfID].GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001941 logger.Warnw("Failed-to-get-onu-info-for-pon-port ", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001942 "device-id": dh.deviceID,
1943 "interface-id": IntfID,
1944 "error": err})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001945 } else {
1946 for i, onu := range onuGemData {
1947 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001948 logger.Debugw("onu-data ", log.Fields{"onu": onu})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001949 if err := dh.clearUNIData(ctx, &onu); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001950 logger.Warnw("Failed-to-clear-uni-data-for-onu", log.Fields{
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001951 "device-id": dh.deviceID,
1952 "onu-device": onu,
1953 "error": err})
1954 }
1955 // Clear flowids for gem cache.
1956 for _, gem := range onu.GemPorts {
1957 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
1958 }
1959 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
1960 dh.resourceMgr.UpdateOnuGemInfo(ctx, IntfID, onuGemData)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001961
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001962 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
1963 break
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001964 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001965 }
1966 }
1967 dh.onus.Delete(onuKey)
1968 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
1969 return nil
1970}
Girish Gowdracefae192020-03-19 18:14:10 -07001971
1972func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
1973 for _, field := range flows.GetOfbFields(flow) {
1974 if field.Type == flows.IN_PORT {
1975 return field.GetPort()
1976 }
1977 }
1978 return InvalidPort
1979}
1980
1981func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
1982 for _, action := range flows.GetActions(flow) {
1983 if action.Type == flows.OUTPUT {
1984 if out := action.GetOutput(); out != nil {
1985 return out.GetPort()
1986 }
1987 }
1988 }
1989 return InvalidPort
1990}
1991
1992func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
1993 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001994 logger.Debugw("increment flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07001995 if inPort != InvalidPort && outPort != InvalidPort {
1996 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
1997 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001998 logger.Debugw("increment flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07001999
2000 dh.lockDevice.Lock()
2001 defer dh.lockDevice.Unlock()
2002 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2003 if !ok {
2004 flowRemoveData = pendingFlowRemoveData{
2005 pendingFlowRemoveCount: 0,
2006 allFlowsRemoved: make(chan struct{}),
2007 }
2008 }
2009 flowRemoveData.pendingFlowRemoveCount++
2010 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2011
Girish Kumar2ad402b2020-03-20 19:45:12 +00002012 logger.Debugw("current flow remove count after increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002013 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2014 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2015 }
2016}
2017
2018func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2019 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002020 logger.Debugw("decrement flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002021 if inPort != InvalidPort && outPort != InvalidPort {
2022 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2023 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002024 logger.Debugw("decrement flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002025
2026 dh.lockDevice.Lock()
2027 defer dh.lockDevice.Unlock()
2028 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002029 logger.Fatalf("flow remove key not found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002030 } else {
2031 if val.pendingFlowRemoveCount > 0 {
2032 val.pendingFlowRemoveCount--
2033 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002034 logger.Debugw("current flow remove count after decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002035 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2036 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2037 // If all flow removes have finished, then close the channel to signal the receiver
2038 // to go ahead with flow adds.
2039 if val.pendingFlowRemoveCount == 0 {
2040 close(val.allFlowsRemoved)
2041 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2042 return
2043 }
2044 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2045 }
2046 }
2047}
2048
2049func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2050 var flowRemoveData pendingFlowRemoveData
2051 var ok bool
2052 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002053 logger.Debugw("wait for flow remove to finish for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002054 if inPort != InvalidPort && outPort != InvalidPort {
2055 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2056 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002057 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 -07002058
2059 dh.lockDevice.RLock()
2060 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002061 logger.Debugw("no pending flow to remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002062 dh.lockDevice.RUnlock()
2063 return
2064 }
2065 dh.lockDevice.RUnlock()
2066
2067 // Wait for all flow removes to finish first
2068 <-flowRemoveData.allFlowsRemoved
2069
Girish Kumar2ad402b2020-03-20 19:45:12 +00002070 logger.Debugw("all flows cleared, handling flow add now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002071 }
2072}
2073
2074func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2075 inPort := getInPortFromFlow(flow)
2076 outPort := getOutPortFromFlow(flow)
2077
2078 if inPort == InvalidPort || outPort == InvalidPort {
2079 return inPort, outPort
2080 }
2081
2082 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2083 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2084 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2085 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2086 return uniPort, outPort
2087 }
2088 }
2089 } else {
2090 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2091 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2092 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2093 return inPort, uniPort
2094 }
2095 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2096 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2097 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2098 return uniPort, outPort
2099 }
2100 }
2101 }
2102
2103 return InvalidPort, InvalidPort
2104}