blob: 7304b9afacc15cacb75efbaa71d89661834ecd7d [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
Girish Gowdra3ab6d212020-03-24 17:33:15 -070092 discOnus sync.Map
93 onus sync.Map
94 portStats *OpenOltStatisticsMgr
95 metrics *pmmetrics.PmMetrics
96 stopCollector chan bool
97 stopHeartbeatCheck chan bool
98 activePorts sync.Map
99 stopIndications chan bool
100 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700101
102 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
103 // subscriber basis for the number of pending flow removes. This data is used
104 // to process all the flow removes for a subscriber before handling flow adds.
105 // Interleaving flow delete and flow add processing has known to cause PON resource
106 // management contentions on a per subscriber bases, so we need ensure ordering.
107 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700108}
109
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700111type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700113 deviceType string
114 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115 onuID uint32
116 intfID uint32
117 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +0000118 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530119 losRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700120}
121
Naga Manjunath7615e552019-10-11 22:35:47 +0530122var pmNames = []string{
123 "rx_bytes",
124 "rx_packets",
125 "rx_mcast_packets",
126 "rx_bcast_packets",
127 "tx_bytes",
128 "tx_packets",
129 "tx_mcast_packets",
130 "tx_bcast_packets",
131}
132
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700133//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530134func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700135 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700136 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700137 device.deviceType = deviceTp
138 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700139 device.onuID = onuID
140 device.intfID = intfID
141 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000142 device.uniPorts = make(map[uint32]struct{})
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530143 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700144 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530145}
146
147//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530148func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700149 var dh DeviceHandler
150 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400151 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400152 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700153 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700154 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700155 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400156 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700157 dh.device = cloned
158 dh.openOLT = adapter
159 dh.exitChannel = make(chan int, 1)
160 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530161 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530162 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530163 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 -0500164 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400165 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700166 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
167
cuilin20187b2a8c32019-03-26 19:52:28 -0700168 //TODO initialize the support classes.
169 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530170}
171
172// start save the device to the data model
173func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700174 dh.lockDevice.Lock()
175 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000176 logger.Debugw("starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700177 // Add the initial device to the local model
Girish Kumar2ad402b2020-03-20 19:45:12 +0000178 logger.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530179}
180
181// stop stops the device dh. Not much to do for now
182func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700183 dh.lockDevice.Lock()
184 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000185 logger.Debug("stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700186 dh.exitChannel <- 1
Girish Kumar2ad402b2020-03-20 19:45:12 +0000187 logger.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530188}
189
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400190func macifyIP(ip net.IP) string {
191 if len(ip) > 0 {
192 oct1 := strconv.FormatInt(int64(ip[12]), 16)
193 oct2 := strconv.FormatInt(int64(ip[13]), 16)
194 oct3 := strconv.FormatInt(int64(ip[14]), 16)
195 oct4 := strconv.FormatInt(int64(ip[15]), 16)
196 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
197 }
198 return ""
199}
200
201func generateMacFromHost(host string) (string, error) {
202 var genmac string
203 var addr net.IP
204 var ips []string
205 var err error
206
Girish Kumar2ad402b2020-03-20 19:45:12 +0000207 logger.Debugw("generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400208
209 if addr = net.ParseIP(host); addr == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000210 logger.Debugw("looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400211
212 if ips, err = net.LookupHost(host); err == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000213 logger.Debugw("dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400214 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000215 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400216 }
217 genmac = macifyIP(addr)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000218 logger.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400219 return genmac, nil
220 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000221 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400222 }
223
224 genmac = macifyIP(addr)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000225 logger.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400226 return genmac, nil
227}
228
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530229func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700230 slist := strings.Split(mac, ":")
231 result := make([]uint32, len(slist))
232 var err error
233 var tmp int64
234 for index, val := range slist {
235 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
236 return []uint32{1, 2, 3, 4, 5, 6}
237 }
238 result[index] = uint32(tmp)
239 }
240 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530241}
242
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700243//GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800244func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530245
David K. Bainbridge794735f2020-02-11 21:01:37 -0800246 switch portType {
247 case voltha.Port_ETHERNET_NNI:
248 return fmt.Sprintf("nni-%d", portNum), nil
249 case voltha.Port_PON_OLT:
250 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700251 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800252
Girish Kumarf26e4882020-03-05 06:49:10 +0000253 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530254}
255
David K. Bainbridge794735f2020-02-11 21:01:37 -0800256func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000257 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700258 if state == "up" {
259 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500260 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500261 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700262 } else {
263 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500264 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700265 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700266 portNum := IntfIDToPortNo(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800267 label, err := GetportLabel(portNum, portType)
268 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000269 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400270 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500271
272 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
273 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000274 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500275 }
276 if device.Ports != nil {
277 for _, dPort := range device.Ports {
278 if dPort.Type == portType && dPort.PortNo == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000279 logger.Debug("port-already-exists-updating-oper-status-of-port")
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500280 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530281 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800282 "device-id": dh.device.Id,
283 "port-type": portType,
284 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000285 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800286
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500287 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800288 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500289 }
290 }
291 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400292 // Now create Port
293 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700294 PortNo: portNum,
295 Label: label,
296 Type: portType,
297 OperStatus: operStatus,
298 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000299 logger.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700300 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700301 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000302 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800303 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000304 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400305 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800306 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530307}
308
309// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800310func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000311 defer logger.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700312 defer func() {
313 dh.lockDevice.Lock()
314 dh.isReadIndicationRoutineActive = false
315 dh.lockDevice.Unlock()
316 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700317 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700318 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700319 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700320 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400321 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530322 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400323 if err != nil || device == nil {
324 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000325 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400326 }
327 // When the device is in DISABLED and Adapter container restarts, we need to
328 // rebuild the locally maintained admin state.
329 if device.AdminState == voltha.AdminState_DISABLED {
330 dh.lockDevice.Lock()
331 dh.adminState = "down"
332 dh.lockDevice.Unlock()
333 }
334
David Bainbridgef5879ca2019-12-13 21:17:54 +0000335 // Create an exponential backoff around re-enabling indications. The
336 // maximum elapsed time for the back off is set to 0 so that we will
337 // continue to retry. The max interval defaults to 1m, but is set
338 // here for code clarity
339 indicationBackoff := backoff.NewExponentialBackOff()
340 indicationBackoff.MaxElapsedTime = 0
341 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700342
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700343 dh.lockDevice.Lock()
344 dh.isReadIndicationRoutineActive = true
345 dh.lockDevice.Unlock()
346
Girish Gowdra3f974912020-03-23 20:35:18 -0700347Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700348 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400349 select {
350 case <-dh.stopIndications:
Girish Kumar2ad402b2020-03-20 19:45:12 +0000351 logger.Debugw("Stopping-collecting-indications-for-OLT", log.Fields{"deviceID:": dh.deviceID})
Girish Gowdra3f974912020-03-23 20:35:18 -0700352 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400353 default:
354 indication, err := indications.Recv()
355 if err == io.EOF {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000356 logger.Infow("EOF for indications", log.Fields{"err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400357 // Use an exponential back off to prevent getting into a tight loop
358 duration := indicationBackoff.NextBackOff()
359 if duration == backoff.Stop {
360 // If we reach a maximum then warn and reset the backoff
361 // timer and keep attempting.
Girish Kumar2ad402b2020-03-20 19:45:12 +0000362 logger.Warnw("Maximum indication backoff reached, resetting backoff timer",
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400363 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
364 indicationBackoff.Reset()
365 }
366 time.Sleep(indicationBackoff.NextBackOff())
Girish Gowdra3f974912020-03-23 20:35:18 -0700367 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
368 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400369 }
370 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000371 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530372 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700373 logger.Errorw("Read indication error", log.Fields{"err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400374 if dh.adminState == "deleted" {
Girish Gowdra3f974912020-03-23 20:35:18 -0700375 logger.Debug("Device deleted stopping the read indication thread")
376 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400377 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700378 // Close the stream, and re-initialize it
379 if err = indications.CloseSend(); err != nil {
380 // Ok to ignore here, because we landed here due to a problem on the stream
381 // In all probability, the closeSend call may fail
382 logger.Debugw("error closing send stream, error ignored", log.Fields{"err": err})
383 }
384 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
385 return err
386 }
387 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400388 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530389 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400390 // Reset backoff if we have a successful receive
391 indicationBackoff.Reset()
392 dh.lockDevice.RLock()
393 adminState := dh.adminState
394 dh.lockDevice.RUnlock()
395 // When OLT is admin down, ignore all indications.
396 if adminState == "down" && !isIndicationAllowedDuringOltAdminDown(indication) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000397 logger.Debugw("olt is admin down, ignore indication", log.Fields{"indication": indication})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400398 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400399 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400400 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700401 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700402 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700403 // Close the send stream
404 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700405
Girish Gowdra3f974912020-03-23 20:35:18 -0700406 return nil
407}
408
409func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
410
411 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
412 if err != nil {
413 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
414 }
415 if indications == nil {
416 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
417 }
418
419 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400420}
421
422// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
423func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
424 switch indication.Data.(type) {
425 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
426 return true
427
428 default:
429 return false
430 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700431}
432
David K. Bainbridge794735f2020-02-11 21:01:37 -0800433func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000434 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000435 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530436 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700437 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530438 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700439 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000440 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800441 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530442 return olterrors.NewErrAdapter("failed-indication", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800443 "device_id": dh.deviceID,
444 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000445 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800446 }
447 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700448}
449
David K. Bainbridge794735f2020-02-11 21:01:37 -0800450// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530451func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400452 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700453 switch indication.Data.(type) {
454 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800455 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530456 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800457 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700458 case *oop.Indication_IntfInd:
459 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800460 go func() {
461 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530462 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800463 }
464 }()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000465 logger.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700466 case *oop.Indication_IntfOperInd:
467 intfOperInd := indication.GetIntfOperInd()
468 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800469 go func() {
470 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530471 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800472 }
473 }()
npujarec5762e2020-01-01 14:08:48 +0530474 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700475 } else if intfOperInd.GetType() == "pon" {
476 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
477 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800478 go func() {
479 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530480 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 }
482 }()
kesavand39e0aa32020-01-28 20:58:50 -0500483 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700484 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000485 logger.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700486 case *oop.Indication_OnuDiscInd:
487 onuDiscInd := indication.GetOnuDiscInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000488 logger.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700489 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800490 go func() {
491 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530492 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800493 }
494 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700495 case *oop.Indication_OnuInd:
496 onuInd := indication.GetOnuInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000497 logger.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800498 go func() {
499 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530500 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800501 }
502 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700503 case *oop.Indication_OmciInd:
504 omciInd := indication.GetOmciInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000505 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 -0800506 go func() {
507 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530508 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800509 }
510 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700511 case *oop.Indication_PktInd:
512 pktInd := indication.GetPktInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000513 logger.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800514 go func() {
515 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530516 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800517 }
518 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700519 case *oop.Indication_PortStats:
520 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530521 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700522 case *oop.Indication_FlowStats:
523 flowStats := indication.GetFlowStats()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000524 logger.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525 case *oop.Indication_AlarmInd:
526 alarmInd := indication.GetAlarmInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000527 logger.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530528 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700529 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530530}
531
532// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530533func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400534 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530535 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400536 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000537 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400538 }
539 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530540}
541
542// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530543func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700544 dh.lockDevice.Lock()
545 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000546 logger.Debug("do-state-down-start")
Girish Gowdrud4245152019-05-10 00:47:31 -0400547
npujarec5762e2020-01-01 14:08:48 +0530548 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400549 if err != nil || device == nil {
550 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000551 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400552 }
553
554 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400555
556 //Update the device oper state and connection status
557 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400558 dh.device = cloned
559
David K. Bainbridge794735f2020-02-11 21:01:37 -0800560 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000561 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400562 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400563
564 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530565 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400566 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000567 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400568 }
569 for _, onuDevice := range onuDevices.Items {
570
571 // Update onu state as down in onu adapter
572 onuInd := oop.OnuIndication{}
573 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800574 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700575 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800576 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530577 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800578 "source": "openolt",
579 "onu-indicator": onuInd,
580 "device-type": onuDevice.Type,
581 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700582 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700583 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400584 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700585 /* Discovered ONUs entries need to be cleared , since after OLT
586 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530587 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000588 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700589 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530590}
591
592// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530593func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400594 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800595 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530596 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800597 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000598 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400599 }
600 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530601}
602
603// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530604func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400605 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530606 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400607 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530608}
609
610// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530611func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000612 logger.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400613
614 // Case where OLT is disabled and then rebooted.
615 if dh.adminState == "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000616 logger.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530617 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400618 if err != nil || device == nil {
619 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530620 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400621 }
622
623 cloned := proto.Clone(device).(*voltha.Device)
624 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
625 cloned.OperStatus = voltha.OperStatus_UNKNOWN
626 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530627 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530628 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400629 }
630
Chaitrashree G S44124192019-08-07 20:21:36 -0400631 // 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 +0530632 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400633 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530634 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400635 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400636 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
637 // all the modules initialized and ready to handle incoming ONUs.
638
639 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
640 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
641 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400642
643 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800644 go func() {
645 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530646 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800647 }
648 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400649 return nil
650 }
651
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700652 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400653 if err != nil || device == nil {
654 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000655 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400656 }
kesavand39e0aa32020-01-28 20:58:50 -0500657 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500658 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000659 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400660 }
661
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400662 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
663 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400664 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530665
cuilin20187b2a8c32019-03-26 19:52:28 -0700666 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800667 go func() {
668 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530669 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800670 }
671 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700672 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530673}
674
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400675func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
676 deviceInfo, err := dh.populateDeviceInfo()
677
678 if err != nil {
679 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
680 }
681 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
682 // Instantiate resource manager
683 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
684 return olterrors.ErrResourceManagerInstantiating
685 }
686
687 // Instantiate flow manager
688 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
689 return olterrors.ErrResourceManagerInstantiating
690
691 }
692 /* TODO: Instantiate Alarm , stats , BW managers */
693 /* Instantiating Event Manager to handle Alarms and KPIs */
694 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
695
696 // Stats config for new device
697 dh.portStats = NewOpenOltStatsMgr(dh)
698
699 return nil
700
701}
702
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400703func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
704 var err error
705 var deviceInfo *oop.DeviceInfo
706
707 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
708
709 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000710 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400711 }
712 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000713 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400714 }
715
Girish Kumar2ad402b2020-03-20 19:45:12 +0000716 logger.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400717 dh.device.Root = true
718 dh.device.Vendor = deviceInfo.Vendor
719 dh.device.Model = deviceInfo.Model
720 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
721 dh.device.HardwareVersion = deviceInfo.HardwareVersion
722 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
723
724 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000725 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400726 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
727 genmac, err := generateMacFromHost(host)
728 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000729 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400730 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000731 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400732 dh.device.MacAddress = genmac
733 } else {
734 dh.device.MacAddress = deviceInfo.DeviceId
735 }
736
737 // Synchronous call to update device - this method is run in its own go routine
738 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000739 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400740 }
741
742 return deviceInfo, nil
743}
744
Naga Manjunath7615e552019-10-11 22:35:47 +0530745func startCollector(dh *DeviceHandler) {
746 // Initial delay for OLT initialization
747 time.Sleep(1 * time.Minute)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000748 logger.Debugf("Starting-Collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530749 context := make(map[string]string)
750 for {
751 select {
752 case <-dh.stopCollector:
Girish Kumar2ad402b2020-03-20 19:45:12 +0000753 logger.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
Naga Manjunath7615e552019-10-11 22:35:47 +0530754 return
755 default:
756 freq := dh.metrics.ToPmConfigs().DefaultFreq
757 time.Sleep(time.Duration(freq) * time.Second)
758 context["oltid"] = dh.deviceID
759 context["devicetype"] = dh.deviceType
760 // NNI Stats
761 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
Girish Kumar2ad402b2020-03-20 19:45:12 +0000762 logger.Debugf("Collect-NNI-Metrics %v", cmnni)
Naga Manjunath7615e552019-10-11 22:35:47 +0530763 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000764 logger.Debugf("Publish-NNI-Metrics")
Naga Manjunath7615e552019-10-11 22:35:47 +0530765 // PON Stats
766 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500767 for i := uint32(0); i < NumPonPORTS; i++ {
768 if val, ok := dh.activePorts.Load(i); ok && val == true {
769 cmpon := dh.portStats.collectPONMetrics(i)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000770 logger.Debugf("Collect-PON-Metrics %v", cmpon)
Naga Manjunath7615e552019-10-11 22:35:47 +0530771
Chaitrashree G Sef088112020-02-03 21:39:27 -0500772 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000773 logger.Debugf("Publish-PON-Metrics")
Chaitrashree G Sef088112020-02-03 21:39:27 -0500774 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530775 }
776 }
777 }
778}
779
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700780//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530781func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400782 dh.transitionMap = NewTransitionMap(dh)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000783 logger.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530784 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530785
786 // Now, set the initial PM configuration for that device
787 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530788 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530789 }
790
791 go startCollector(dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400792 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530793}
794
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700795//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530796func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700797 return &ic.SwitchCapability{
798 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530799 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700800 HwDesc: "open_pon",
801 SwDesc: "open_pon",
802 SerialNum: dh.device.SerialNumber,
803 },
804 SwitchFeatures: &of.OfpSwitchFeatures{
805 NBuffers: 256,
806 NTables: 2,
807 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
808 of.OfpCapabilities_OFPC_TABLE_STATS |
809 of.OfpCapabilities_OFPC_PORT_STATS |
810 of.OfpCapabilities_OFPC_GROUP_STATS),
811 },
812 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530813}
814
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700815//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530816func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700817 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700818 return &ic.PortCapability{
819 Port: &voltha.LogicalPort{
820 OfpPort: &of.OfpPort{
821 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
822 Config: 0,
823 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700824 Curr: capacity,
825 Advertised: capacity,
826 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700827 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
828 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
829 },
830 DeviceId: dh.device.Id,
831 DevicePortNo: uint32(portNo),
832 },
833 }, nil
834}
835
David K. Bainbridge794735f2020-02-11 21:01:37 -0800836func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000837 logger.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700838 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700839 var deviceID string
840 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700841
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700842 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530843
844 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
845
Girish Kumar2ad402b2020-03-20 19:45:12 +0000846 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 -0700847 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700848 kwargs := make(map[string]interface{})
849 kwargs["onu_id"] = omciInd.OnuId
850 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700851
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700852 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
853 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530854 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800855 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000856 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700857 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700858 deviceType = onuDevice.Type
859 deviceID = onuDevice.Id
860 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
861 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530862 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700863 } else {
864 //found in cache
Girish Kumar2ad402b2020-03-20 19:45:12 +0000865 logger.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530866 deviceType = onuInCache.(*OnuDevice).deviceType
867 deviceID = onuInCache.(*OnuDevice).deviceID
868 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700869 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700870
871 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800872 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700873 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800874 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530875 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800876 "source": dh.deviceType,
877 "destination": deviceType,
878 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000879 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700880 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800881 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530882}
883
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700884//ProcessInterAdapterMessage sends the proxied messages to the target device
885// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
886// is meant, and then send the unmarshalled omci message to this onu
887func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000888 logger.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700889 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700890 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700891 fromTopic := msg.Header.FromTopic
892 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700893 toDeviceID := msg.Header.ToDeviceId
894 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700895
Girish Kumar2ad402b2020-03-20 19:45:12 +0000896 logger.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700897
898 msgBody := msg.GetBody()
899
900 omciMsg := &ic.InterAdapterOmciMessage{}
901 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000902 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700903 }
904
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700905 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700906 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
907 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530908 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800909 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000910 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700911 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000912 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 -0800913 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530914 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800915 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000916 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800917 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700918 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000919 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 -0800920 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530921 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800922 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000923 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800924 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700925 }
926
927 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000928 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700929 }
930 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530931}
932
David K. Bainbridge794735f2020-02-11 21:01:37 -0800933func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700934 var intfID uint32
935 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000936 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700937 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938 intfID = onuDevice.ProxyAddress.GetChannelId()
939 onuID = onuDevice.ProxyAddress.GetOnuId()
940 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700941 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 intfID = omciMsg.GetProxyAddress().GetChannelId()
943 onuID = omciMsg.GetProxyAddress().GetOnuId()
944 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700945 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700946 if connectStatus != voltha.ConnectStatus_REACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000947 logger.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800948
Thomas Lee S94109f12020-03-03 16:39:29 +0530949 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800950 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000951 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700952 }
953
lcuie24ef182019-04-29 22:58:36 -0700954 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
955 isHexString := false
956 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
957 if decodeerr == nil {
958 isHexString = true
959 }
960
961 // 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.
962 var omciMessage *oop.OmciMsg
963 if isHexString {
964 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
965 } else {
966 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
967 hex.Encode(hexPkt, omciMsg.Message)
968 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
969 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700970
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700971 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
972 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530973 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800974 "interface-id": intfID,
975 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000976 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700977 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000978 logger.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800979 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700980}
981
David K. Bainbridge794735f2020-02-11 21:01:37 -0800982func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000983 logger.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
npujarec5762e2020-01-01 14:08:48 +0530984 dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber)
cuilin20187b2a8c32019-03-26 19:52:28 -0700985 // TODO: need resource manager
986 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700987 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530988 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400989 st, _ := status.FromError(err)
990 if st.Code() == codes.AlreadyExists {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000991 logger.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400992 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000993 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400994 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700995 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000996 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
cuilin20187b2a8c32019-03-26 19:52:28 -0700997 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800998 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700999}
1000
David K. Bainbridge794735f2020-02-11 21:01:37 -08001001func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001002
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001003 channelID := onuDiscInd.GetIntfId()
1004 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001005
Girish Kumar2ad402b2020-03-20 19:45:12 +00001006 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301007
cuilin20187b2a8c32019-03-26 19:52:28 -07001008 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001009 if sn != "" {
1010 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001011 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001012 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001013 }
1014
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301015 var alarmInd oop.OnuAlarmIndication
1016 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001017 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301018
1019 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1020 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1021 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1022 OnuLosRaise event sent for it */
1023 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1024 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1025 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001026 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301027 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1028 "currentIntfId": onuDiscInd.GetIntfId()})
1029 // TODO:: Should we need to ignore raising OnuLosClear event
1030 // when onu connected to different PON?
1031 }
1032 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1033 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1034 alarmInd.LosStatus = statusCheckOff
1035 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1036 }
1037 return true
1038 })
1039
Girish Kumar2ad402b2020-03-20 19:45:12 +00001040 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001041 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001042 }
1043
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001044 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001045
1046 // check the ONU is already know to the OLT
1047 // NOTE the second time the ONU is discovered this should return a device
1048 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1049
1050 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001051 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 -08001052 if e, ok := status.FromError(err); ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001053 logger.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001054 switch e.Code() {
1055 case codes.Internal:
1056 // this probably means NOT FOUND, so just create a new device
1057 onuDevice = nil
1058 case codes.DeadlineExceeded:
1059 // if the call times out, cleanup and exit
1060 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001061 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001062 }
1063 }
1064 }
1065
1066 if onuDevice == nil {
1067 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Girish Kumar2ad402b2020-03-20 19:45:12 +00001068 logger.Infow("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001069 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001070 ponintfid := onuDiscInd.GetIntfId()
1071 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301072 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001073 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001074
Girish Kumar2ad402b2020-03-20 19:45:12 +00001075 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001076
1077 if err != nil {
1078 // if we can't create an ID in resource manager,
1079 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001080 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001081 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001082 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001083 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001084 }
1085
1086 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1087 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001088 dh.discOnus.Delete(sn)
1089 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 +05301090 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001091 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001092 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001093 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001094 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Girish Kumar2ad402b2020-03-20 19:45:12 +00001095 logger.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001096 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001097
1098 // we can now use the existing ONU Id
1099 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001100 //Insert the ONU into cache to use in OnuIndication.
1101 //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 +00001102 logger.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
Matteo Scandolo945e4012019-12-12 14:16:11 -08001103 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001104 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001105
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301106 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301107 dh.onus.Store(onuKey, onuDev)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001108 logger.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001109
David K. Bainbridge794735f2020-02-11 21:01:37 -08001110 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301111 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001112 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001113 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001114 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001115 logger.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301117 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001118 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001119 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001120 }
1121 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001122}
1123
David K. Bainbridge794735f2020-02-11 21:01:37 -08001124func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001125 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1126
1127 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001128 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001129 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001130 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001131 foundInCache := false
Girish Kumar2ad402b2020-03-20 19:45:12 +00001132 logger.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
Scott Baker7eb0a932019-07-26 10:33:22 -07001133 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001134 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301135
David K. Bainbridge794735f2020-02-11 21:01:37 -08001136 errFields := log.Fields{"device-id": dh.device.Id}
1137
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301138 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1139
Mahir Gunyele77977b2019-06-27 05:36:22 -07001140 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1141 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1143 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001144 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001145 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1146 if serialNumber != "" {
1147 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001149 } else {
1150 kwargs["onu_id"] = onuInd.OnuId
1151 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001152 errFields["onu-id"] = onuInd.OnuId
1153 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001154 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001155 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001156 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001157
David K. Bainbridge794735f2020-02-11 21:01:37 -08001158 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001159 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001160 }
1161
David K. Bainbridge794735f2020-02-11 21:01:37 -08001162 if onuDevice.ParentPortNo != ponPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001163 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001164 "previousIntfId": onuDevice.ParentPortNo,
1165 "currentIntfId": ponPort})
1166 }
1167
1168 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001169 logger.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1171 "received_onu_id": onuInd.OnuId})
1172 }
1173 if !foundInCache {
1174 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1175
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301176 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 -08001177
1178 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001179 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001180 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001181 }
1182 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001183}
1184
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001185func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301186 ctx := context.TODO()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001187 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 +00001188 if onuInd.AdminState == "down" {
1189 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1190 if onuInd.OperState != "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001191 logger.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001192 onuInd.OperState = "down"
1193 }
1194 }
1195
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 switch onuInd.OperState {
1197 case "down":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001198 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 -07001199 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301200 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001201 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1202 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301203 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001204 "onu-indicator": onuInd,
1205 "source": "openolt",
1206 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001207 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001208 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001209 case "up":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001210 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 -04001211 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301212 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001213 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1214 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301215 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001216 "onu-indicator": onuInd,
1217 "source": "openolt",
1218 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001219 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001220 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001222 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001223 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001225}
1226
cuilin20187b2a8c32019-03-26 19:52:28 -07001227func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1228 if serialNum != nil {
1229 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001230 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001231 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001232}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001233func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1234 decodedStr, err := hex.DecodeString(serialNum[4:])
1235 if err != nil {
1236 return nil, err
1237 }
1238 return &oop.SerialNumber{
1239 VendorId: []byte(serialNum[:4]),
1240 VendorSpecific: []byte(decodedStr),
1241 }, nil
1242}
cuilin20187b2a8c32019-03-26 19:52:28 -07001243
1244func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1245 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001246 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001247 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1248 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1249 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1250 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1251 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1252 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1253 return tmp
1254}
1255
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001256//UpdateFlowsBulk upates the bulk flow
1257func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301258 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001259}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001260
1261//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001263 logger.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001264 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001265 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001266 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001267 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001268 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001269 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001270 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001271 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001272 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001273 logger.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301275}
1276
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001277// SendPacketInToCore sends packet-in to core
1278// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1279// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001280func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001281 logger.Debugw("send-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001282 "port": logicalPort,
1283 "packet": hex.EncodeToString(packetPayload),
1284 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001285 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301286 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 "source": "adapter",
1288 "destination": "core",
1289 "device-id": dh.device.Id,
1290 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001291 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001292 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001293 logger.Debugw("Sent packet-in to core successfully", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001294 "packet": hex.EncodeToString(packetPayload),
1295 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001296 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001297}
1298
A R Karthick1f85b802019-10-11 05:06:05 +00001299// AddUniPortToOnu adds the uni port to the onu device
1300func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1301 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301302
1303 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001304 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301305 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1306 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001307 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001308 }
1309 }
1310}
1311
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001312//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301313func (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 +00001314 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 +01001315
1316 var errorsList []error
1317
Girish Gowdru0c588b22019-04-23 23:24:56 -04001318 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001319 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001320 dh.incrementActiveFlowRemoveCount(flow)
1321
Girish Kumar2ad402b2020-03-20 19:45:12 +00001322 logger.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001323 err := dh.flowMgr.RemoveFlow(ctx, flow)
1324 if err != nil {
1325 errorsList = append(errorsList, err)
1326 }
1327
1328 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001329 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301330
1331 for _, flow := range flows.ToAdd.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001332 logger.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001333 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1334 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001335 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1336 if err != nil {
1337 errorsList = append(errorsList, err)
1338 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301339 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001340 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001341 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001342 for _, flow := range flows.ToRemove.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001343 logger.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001344 // dh.flowMgr.RemoveFlow(flow)
1345 }
1346 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001347
Girish Gowdracefae192020-03-19 18:14:10 -07001348 // 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 +00001349 if groups != nil {
1350 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001351 err := dh.flowMgr.AddGroup(ctx, group)
1352 if err != nil {
1353 errorsList = append(errorsList, err)
1354 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001355 }
1356 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001357 err := dh.flowMgr.ModifyGroup(ctx, group)
1358 if err != nil {
1359 errorsList = append(errorsList, err)
1360 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001361 }
1362 if len(groups.ToRemove.Items) != 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001363 logger.Debug("Group delete operation is not supported for now")
Esin Karamanccb714b2019-11-29 15:02:06 +00001364 }
1365 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001366 if len(errorsList) > 0 {
1367 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1368 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001369 logger.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001370 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301371}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001372
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001373//DisableDevice disables the given device
1374//It marks the following for the given device:
1375//Device-Handler Admin-State : down
1376//Device Port-State: UNKNOWN
1377//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001378func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001379 /* On device disable ,admin state update has to be done prior sending request to agent since
1380 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001381 dh.lockDevice.Lock()
1382 dh.adminState = "down"
1383 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001384 if dh.Client != nil {
1385 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1386 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001387 dh.lockDevice.Lock()
1388 dh.adminState = "up"
1389 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001390 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001391 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001392 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001393 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001394 logger.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001395 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001396 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301397
1398 dh.discOnus = sync.Map{}
1399 dh.onus = sync.Map{}
1400
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301401 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001402 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001403 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1404 for _, port := range cloned.Ports {
1405 if port.GetType() == voltha.Port_PON_OLT {
1406 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1407 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001408 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001409 }
1410 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001411 }
1412
Girish Kumar2ad402b2020-03-20 19:45:12 +00001413 logger.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001414 return nil
1415}
1416
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301417func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001418
1419 // Update onu state as unreachable in onu adapter
1420 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301421 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001422 //get the child device for the parent device
1423 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1424 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001425 logger.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001426 }
1427 if onuDevices != nil {
1428 for _, onuDevice := range onuDevices.Items {
1429 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1430 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1431 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001432 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001433 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1434 }
1435
1436 }
1437 }
1438
1439}
1440
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001441//ReenableDevice re-enables the olt device after disable
1442//It marks the following for the given device:
1443//Device-Handler Admin-State : up
1444//Device Port-State: ACTIVE
1445//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001446func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001447 dh.lockDevice.Lock()
1448 dh.adminState = "up"
1449 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301450
1451 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1452 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301453 dh.lockDevice.Lock()
1454 dh.adminState = "down"
1455 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001456 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301457 }
1458 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001459 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001460
1461 cloned := proto.Clone(device).(*voltha.Device)
1462 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001463
kdarapu1afeceb2020-02-12 01:38:09 -05001464 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001465 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001466 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001467 //Update the device oper status as ACTIVE
1468 cloned.OperStatus = voltha.OperStatus_ACTIVE
1469 dh.device = cloned
1470
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001471 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301472 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001473 "device-id": device.Id,
1474 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001475 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001476 }
kesavand39e0aa32020-01-28 20:58:50 -05001477
Girish Kumar2ad402b2020-03-20 19:45:12 +00001478 logger.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001479
1480 return nil
1481}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001482
npujarec5762e2020-01-01 14:08:48 +05301483func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001484 var uniID uint32
1485 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301486 for _, port := range onu.UniPorts {
1487 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001488 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001489 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301490 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001491 logger.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001492 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001493 logger.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301494 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001495 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301496 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001497 }
npujarec5762e2020-01-01 14:08:48 +05301498 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001499 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301500 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001501 logger.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001502 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001503 logger.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301504 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001505 logger.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001506 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001507 logger.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301508 }
npujarec5762e2020-01-01 14:08:48 +05301509 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1510 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001511 logger.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301512 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001513 logger.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301514 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001515 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 +00001516 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001517 }
1518 return nil
1519}
1520
npujarec5762e2020-01-01 14:08:48 +05301521func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001522 nniUniID := -1
1523 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301524
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001525 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001526 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001527 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001528 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301529 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301530 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001531 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001532 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001533 logger.Debugw("NNI are ", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301534 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301535 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001536 logger.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301537 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301538 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301539 }
npujarec5762e2020-01-01 14:08:48 +05301540 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001541 }
npujarec5762e2020-01-01 14:08:48 +05301542 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001543 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301544 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001545 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001546}
1547
1548// 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 +05301549func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001550 logger.Debug("Function entry delete device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001551 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001552 if dh.adminState == "deleted" {
1553 dh.lockDevice.Unlock()
1554 return nil
1555 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001556 dh.adminState = "deleted"
1557 dh.lockDevice.Unlock()
1558 /* Clear the KV store data associated with the all the UNI ports
1559 This clears up flow data and also resource map data for various
1560 other pon resources like alloc_id and gemport_id
1561 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001562 go dh.cleanupDeviceResources(ctx)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001563 logger.Debug("Removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001564 // Stop the Stats collector
1565 dh.stopCollector <- true
1566 // stop the heartbeat check routine
1567 dh.stopHeartbeatCheck <- true
1568 //Reset the state
1569 if dh.Client != nil {
1570 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
1571 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
1572 }
1573 }
1574 cloned := proto.Clone(device).(*voltha.Device)
1575 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1576 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1577 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1578 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1579 "device-id": device.Id,
1580 "connect-status": cloned.ConnectStatus,
1581 "oper-status": cloned.OperStatus}, err).Log()
1582 }
1583 return nil
1584}
1585func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001586 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301587 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1588 var ponPort uint32
1589 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1590 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301591 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301592 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301593 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001594 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001595 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301596 }
1597 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301598 onuID := make([]uint32, 1)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001599 logger.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301600 if err = dh.clearUNIData(ctx, &onu); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001601 logger.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301602 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301603 // Clear flowids for gem cache.
1604 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301605 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301606 }
1607 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301608 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301609 }
npujarec5762e2020-01-01 14:08:48 +05301610 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301611 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301612 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301613 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001614 logger.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001615 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001616 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001617 /* Clear the flows from KV store associated with NNI port.
1618 There are mostly trap rules from NNI port (like LLDP)
1619 */
npujarec5762e2020-01-01 14:08:48 +05301620 if err := dh.clearNNIData(ctx); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001621 logger.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001622 }
A R Karthick1f85b802019-10-11 05:06:05 +00001623
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001624 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301625 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001626 }
A R Karthick1f85b802019-10-11 05:06:05 +00001627
Devmalya Paul495b94a2019-08-27 19:42:00 -04001628 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301629 dh.onus.Range(func(key interface{}, value interface{}) bool {
1630 dh.onus.Delete(key)
1631 return true
1632 })
1633
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001634 /*Delete discovered ONU map for the device*/
1635 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1636 dh.discOnus.Delete(key)
1637 return true
1638 })
1639
Devmalya Paul495b94a2019-08-27 19:42:00 -04001640 return nil
1641}
1642
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001643//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001644func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1645 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001646 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001647 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001648 logger.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001649 return nil
1650}
1651
David K. Bainbridge794735f2020-02-11 21:01:37 -08001652func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001653 logger.Debugw("Received packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001654 "packet-indication": *packetIn,
1655 "packet": hex.EncodeToString(packetIn.Pkt),
1656 })
npujarec5762e2020-01-01 14:08:48 +05301657 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001658 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001659 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001660 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001661 logger.Debugw("sending packet-in to core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001662 "logicalPortNum": logicalPortNum,
1663 "packet": hex.EncodeToString(packetIn.Pkt),
1664 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001665 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301666 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001667 "destination": "core",
1668 "source": dh.deviceType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001669 "packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001670 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001671 logger.Debugw("Success sending packet-in to core!", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001672 "packet": hex.EncodeToString(packetIn.Pkt),
1673 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001675}
1676
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001677// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301678func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001679 logger.Debugw("incoming-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001680 "deviceID": dh.deviceID,
1681 "egress_port_no": egressPortNo,
1682 "pkt-length": len(packet.Data),
1683 "packet": hex.EncodeToString(packet.Data),
1684 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001685
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001686 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001687 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001688 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1689 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301690 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1691 // Do not packet-out lldp packets on uni port.
1692 // ONOS has no clue about uni/nni ports, it just packets out on all
1693 // available ports on the Logical Switch. It should not be interested
1694 // in the UNI links.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001695 logger.Debug("dropping-lldp-packet-out-on-uni")
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301696 return nil
1697 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001698 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1699 if innerEthType == 0x8100 {
1700 // q-in-q 802.1ad or 802.1q double tagged packet.
1701 // slice out the outer tag.
1702 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001703 logger.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001704 }
1705 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001706 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1707 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001708 uniID := UniIDFromPortNum(uint32(egressPortNo))
1709
npujarec5762e2020-01-01 14:08:48 +05301710 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001711 if err != nil {
1712 // In this case the openolt agent will receive the gemPortID as 0.
1713 // The agent tries to retrieve the gemPortID in this case.
1714 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001715 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001716 "packet": hex.EncodeToString(packet.Data),
1717 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001718 }
1719
1720 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001721
Girish Kumar2ad402b2020-03-20 19:45:12 +00001722 logger.Debugw("sending-packet-to-onu", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001723 "egress_port_no": egressPortNo,
1724 "IntfId": intfID,
1725 "onuID": onuID,
1726 "uniID": uniID,
1727 "gemPortID": gemPortID,
1728 "packet": hex.EncodeToString(packet.Data),
1729 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001730
npujarec5762e2020-01-01 14:08:48 +05301731 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301732 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001733 "source": "adapter",
1734 "destination": "onu",
1735 "egress-port-number": egressPortNo,
1736 "interface-id": intfID,
1737 "oni-id": onuID,
1738 "uni-id": uniID,
1739 "gem-port-id": gemPortID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001740 "packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001741 }
1742 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001743 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1744 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001745 return olterrors.NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001746 }
1747 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001748
Girish Kumar2ad402b2020-03-20 19:45:12 +00001749 logger.Debugw("sending-packet-to-nni", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001750 "uplink_pkt": uplinkPkt,
1751 "packet": hex.EncodeToString(packet.Data),
1752 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001753
npujarec5762e2020-01-01 14:08:48 +05301754 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001755 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001756 }
1757 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001758 logger.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001759 "egress_port_no": egressPortNo,
1760 "egressPortType": egressPortType,
1761 "packet": hex.EncodeToString(packet.Data),
1762 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001763 }
1764 return nil
1765}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001766
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001767func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1768 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001769}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301770
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001771func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301772 // start the heartbeat check towards the OLT.
1773 var timerCheck *time.Timer
1774
1775 for {
1776 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1777 select {
1778 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001779 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1780 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001781 logger.Error("Hearbeat failed")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301782 if timerCheck == nil {
1783 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001784 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301785 }
1786 } else {
1787 if timerCheck != nil {
1788 if timerCheck.Stop() {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001789 logger.Debug("We got hearbeat within the timeout")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301790 }
1791 timerCheck = nil
1792 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001793 logger.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301794 }
1795 cancel()
1796 case <-dh.stopHeartbeatCheck:
Girish Kumar2ad402b2020-03-20 19:45:12 +00001797 logger.Debug("Stopping heart beat check")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301798 return
1799 }
1800 }
1801}
1802
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001803func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1804 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1805 if err != nil || device == nil {
1806 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1807 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301808
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001809 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1810 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1811 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1812 }
1813 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1814 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1815 }
1816 go dh.cleanupDeviceResources(ctx)
1817
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001818 dh.lockDevice.RLock()
1819 // Stop the read indication only if it the routine is active
1820 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1821 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1822 // on next execution of the readIndication routine.
1823 if dh.isReadIndicationRoutineActive {
1824 dh.stopIndications <- true
1825 }
1826 dh.lockDevice.RUnlock()
1827
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001828 dh.transitionMap.Handle(ctx, DeviceInit)
1829
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301830 }
1831}
kesavand39e0aa32020-01-28 20:58:50 -05001832
1833// EnablePort to enable Pon interface
1834func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001835 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001836 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001837}
1838
1839// DisablePort to disable pon interface
1840func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001841 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001842 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001843}
1844
kdarapu1afeceb2020-02-12 01:38:09 -05001845//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1846func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301847 ctx := context.Background()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001848 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001849 if port.GetType() == voltha.Port_ETHERNET_NNI {
1850 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001851 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
kesavand39e0aa32020-01-28 20:58:50 -05001852 log.Fields{"Device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301853 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001854 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001855 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001856 }
1857 // fetch interfaceid from PortNo
1858 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1859 ponIntf := &oop.Interface{IntfId: ponID}
1860 var operStatus voltha.OperStatus_Types
1861 if enablePort {
1862 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301863 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001864
1865 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301866 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001867 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001868 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001869 }
1870 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001871 dh.activePorts.Store(ponID, true)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001872 logger.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001873 } else {
1874 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301875 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001876 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301877 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001878 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001879 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001880 }
1881 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001882 dh.activePorts.Store(ponID, false)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001883 logger.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001884 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001885 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 +05301886 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001887 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001888 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001889 }
1890 return nil
1891}
1892
kdarapu1afeceb2020-02-12 01:38:09 -05001893//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1894func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001895 cloned := proto.Clone(device).(*voltha.Device)
1896 // Disable the port and update the oper_port_status to core
1897 // if the Admin state of the port is disabled on reboot and re-enable device.
1898 for _, port := range cloned.Ports {
1899 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001900 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301901 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001902 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001903 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001904 }
1905 }
1906 }
1907 return nil
1908}
1909
1910//populateActivePorts to populate activePorts map
1911func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001912 logger.Info("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001913 for _, port := range device.Ports {
1914 if port.Type == voltha.Port_ETHERNET_NNI {
1915 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001916 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001917 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001918 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001919 }
1920 }
1921 if port.Type == voltha.Port_PON_OLT {
1922 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001923 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001924 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001925 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001926 }
1927 }
1928 }
1929}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001930
1931// ChildDeviceLost deletes ONU and clears pon resources related to it.
1932func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001933 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001934 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1935 onuKey := dh.formOnuKey(IntfID, onuID)
1936 onuDevice, ok := dh.onus.Load(onuKey)
1937 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301938 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001939 log.Fields{
1940 "device-id": dh.deviceID,
1941 "onu-id": onuID,
1942 "interface-id": IntfID}, nil).Log()
1943 }
1944 var sn *oop.SerialNumber
1945 var err error
1946 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301947 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001948 log.Fields{
1949 "devicer-id": dh.deviceID,
1950 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1951 }
1952 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1953 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301954 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001955 "device-id": dh.deviceID,
1956 "onu-id": onuID}, err).Log()
1957 }
1958 //clear PON resources associated with ONU
1959 var onuGemData []rsrcMgr.OnuGemInfo
1960 if err := dh.resourceMgr.ResourceMgrs[IntfID].GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001961 logger.Warnw("Failed-to-get-onu-info-for-pon-port ", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001962 "device-id": dh.deviceID,
1963 "interface-id": IntfID,
1964 "error": err})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001965 } else {
1966 for i, onu := range onuGemData {
1967 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001968 logger.Debugw("onu-data ", log.Fields{"onu": onu})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001969 if err := dh.clearUNIData(ctx, &onu); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001970 logger.Warnw("Failed-to-clear-uni-data-for-onu", log.Fields{
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001971 "device-id": dh.deviceID,
1972 "onu-device": onu,
1973 "error": err})
1974 }
1975 // Clear flowids for gem cache.
1976 for _, gem := range onu.GemPorts {
1977 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
1978 }
1979 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
1980 dh.resourceMgr.UpdateOnuGemInfo(ctx, IntfID, onuGemData)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001981
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001982 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
1983 break
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001984 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001985 }
1986 }
1987 dh.onus.Delete(onuKey)
1988 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
1989 return nil
1990}
Girish Gowdracefae192020-03-19 18:14:10 -07001991
1992func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
1993 for _, field := range flows.GetOfbFields(flow) {
1994 if field.Type == flows.IN_PORT {
1995 return field.GetPort()
1996 }
1997 }
1998 return InvalidPort
1999}
2000
2001func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2002 for _, action := range flows.GetActions(flow) {
2003 if action.Type == flows.OUTPUT {
2004 if out := action.GetOutput(); out != nil {
2005 return out.GetPort()
2006 }
2007 }
2008 }
2009 return InvalidPort
2010}
2011
2012func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2013 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002014 logger.Debugw("increment flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002015 if inPort != InvalidPort && outPort != InvalidPort {
2016 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2017 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002018 logger.Debugw("increment flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002019
2020 dh.lockDevice.Lock()
2021 defer dh.lockDevice.Unlock()
2022 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2023 if !ok {
2024 flowRemoveData = pendingFlowRemoveData{
2025 pendingFlowRemoveCount: 0,
2026 allFlowsRemoved: make(chan struct{}),
2027 }
2028 }
2029 flowRemoveData.pendingFlowRemoveCount++
2030 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2031
Girish Kumar2ad402b2020-03-20 19:45:12 +00002032 logger.Debugw("current flow remove count after increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002033 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2034 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2035 }
2036}
2037
2038func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2039 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002040 logger.Debugw("decrement flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002041 if inPort != InvalidPort && outPort != InvalidPort {
2042 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2043 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002044 logger.Debugw("decrement flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002045
2046 dh.lockDevice.Lock()
2047 defer dh.lockDevice.Unlock()
2048 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002049 logger.Fatalf("flow remove key not found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002050 } else {
2051 if val.pendingFlowRemoveCount > 0 {
2052 val.pendingFlowRemoveCount--
2053 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002054 logger.Debugw("current flow remove count after decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002055 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2056 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2057 // If all flow removes have finished, then close the channel to signal the receiver
2058 // to go ahead with flow adds.
2059 if val.pendingFlowRemoveCount == 0 {
2060 close(val.allFlowsRemoved)
2061 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2062 return
2063 }
2064 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2065 }
2066 }
2067}
2068
2069func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2070 var flowRemoveData pendingFlowRemoveData
2071 var ok bool
2072 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002073 logger.Debugw("wait for flow remove to finish for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002074 if inPort != InvalidPort && outPort != InvalidPort {
2075 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2076 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002077 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 -07002078
2079 dh.lockDevice.RLock()
2080 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002081 logger.Debugw("no pending flow to remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002082 dh.lockDevice.RUnlock()
2083 return
2084 }
2085 dh.lockDevice.RUnlock()
2086
2087 // Wait for all flow removes to finish first
2088 <-flowRemoveData.allFlowsRemoved
2089
Girish Kumar2ad402b2020-03-20 19:45:12 +00002090 logger.Debugw("all flows cleared, handling flow add now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002091 }
2092}
2093
2094func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2095 inPort := getInPortFromFlow(flow)
2096 outPort := getOutPortFromFlow(flow)
2097
2098 if inPort == InvalidPort || outPort == InvalidPort {
2099 return inPort, outPort
2100 }
2101
2102 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2103 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2104 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2105 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2106 return uniPort, outPort
2107 }
2108 }
2109 } else {
2110 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2111 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2112 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2113 return inPort, uniPort
2114 }
2115 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2116 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2117 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2118 return uniPort, outPort
2119 }
2120 }
2121 }
2122
2123 return InvalidPort, InvalidPort
2124}