blob: 2e879e1e6ac3c4cd039a2d4490b3b56e45cae810 [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
cuilin20187b2a8c32019-03-26 19:52:28 -070024 "fmt"
25 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040026 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070027 "strconv"
28 "strings"
29 "sync"
30 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053031
Shrey Baid807a2a02020-04-09 12:52:45 +053032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33
Chaitrashree G Sb2b62dd2019-07-24 21:47:04 -040034 "google.golang.org/grpc/codes"
35
Matteo Scandolo945e4012019-12-12 14:16:11 -080036 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070037 "github.com/gogo/protobuf/proto"
38 "github.com/golang/protobuf/ptypes"
Esin Karamanccb714b2019-11-29 15:02:06 +000039 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
40 "github.com/opencord/voltha-lib-go/v3/pkg/log"
41 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Thomas Lee S94109f12020-03-03 16:39:29 +053042 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080043 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000044 "github.com/opencord/voltha-protos/v3/go/common"
45 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
46 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
47 oop "github.com/opencord/voltha-protos/v3/go/openolt"
48 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070049 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040050 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053051)
52
salmansiddiqui7ac62132019-08-22 03:58:50 +000053// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040054const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000055 MaxRetry = 10
56 MaxTimeOutInMs = 500
Girish Gowdracefae192020-03-19 18:14:10 -070057 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040058)
59
Girish Gowdracefae192020-03-19 18:14:10 -070060// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
61type pendingFlowRemoveDataKey struct {
62 intfID uint32
63 onuID uint32
64 uniID uint32
65}
66
67// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
68// This holds the number of pending flow removes and also a signal channel to
69// to indicate the receiver when all flow removes are handled
70type pendingFlowRemoveData struct {
71 pendingFlowRemoveCount uint32
72 allFlowsRemoved chan struct{}
73}
74
Phaneendra Manda4c62c802019-03-06 21:37:49 +053075//DeviceHandler will interact with the OLT device.
76type DeviceHandler struct {
cuilin20187b2a8c32019-03-26 19:52:28 -070077 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053078 coreProxy adapterif.CoreProxy
79 AdapterProxy adapterif.AdapterProxy
80 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070081 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070082 exitChannel chan int
83 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053084 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070085 transitionMap *TransitionMap
86 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053087 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040088 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053089 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053090
Girish Gowdra3ab6d212020-03-24 17:33:15 -070091 discOnus sync.Map
92 onus sync.Map
93 portStats *OpenOltStatisticsMgr
94 metrics *pmmetrics.PmMetrics
95 stopCollector chan bool
96 stopHeartbeatCheck chan bool
97 activePorts sync.Map
98 stopIndications chan bool
99 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700100
101 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
102 // subscriber basis for the number of pending flow removes. This data is used
103 // to process all the flow removes for a subscriber before handling flow adds.
104 // Interleaving flow delete and flow add processing has known to cause PON resource
105 // management contentions on a per subscriber bases, so we need ensure ordering.
106 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700107}
108
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700109//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700112 deviceType string
113 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 onuID uint32
115 intfID uint32
116 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +0000117 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530118 losRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700119}
120
Naga Manjunath7615e552019-10-11 22:35:47 +0530121var pmNames = []string{
122 "rx_bytes",
123 "rx_packets",
124 "rx_mcast_packets",
125 "rx_bcast_packets",
126 "tx_bytes",
127 "tx_packets",
128 "tx_mcast_packets",
129 "tx_bcast_packets",
130}
131
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700132//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530133func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700135 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700136 device.deviceType = deviceTp
137 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700138 device.onuID = onuID
139 device.intfID = intfID
140 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000141 device.uniPorts = make(map[uint32]struct{})
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530142 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700143 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530144}
145
146//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530147func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700148 var dh DeviceHandler
149 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400150 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400151 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700152 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700153 dh.device = cloned
154 dh.openOLT = adapter
155 dh.exitChannel = make(chan int, 1)
156 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530157 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530158 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530159 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500160 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400161 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700162 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
163
cuilin20187b2a8c32019-03-26 19:52:28 -0700164 //TODO initialize the support classes.
165 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530166}
167
168// start save the device to the data model
169func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700170 dh.lockDevice.Lock()
171 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000172 logger.Debugw("starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700173 // Add the initial device to the local model
Girish Kumar2ad402b2020-03-20 19:45:12 +0000174 logger.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530175}
176
177// stop stops the device dh. Not much to do for now
178func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700179 dh.lockDevice.Lock()
180 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000181 logger.Debug("stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700182 dh.exitChannel <- 1
Girish Kumar2ad402b2020-03-20 19:45:12 +0000183 logger.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530184}
185
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400186func macifyIP(ip net.IP) string {
187 if len(ip) > 0 {
188 oct1 := strconv.FormatInt(int64(ip[12]), 16)
189 oct2 := strconv.FormatInt(int64(ip[13]), 16)
190 oct3 := strconv.FormatInt(int64(ip[14]), 16)
191 oct4 := strconv.FormatInt(int64(ip[15]), 16)
192 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
193 }
194 return ""
195}
196
197func generateMacFromHost(host string) (string, error) {
198 var genmac string
199 var addr net.IP
200 var ips []string
201 var err error
202
Girish Kumar2ad402b2020-03-20 19:45:12 +0000203 logger.Debugw("generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400204
205 if addr = net.ParseIP(host); addr == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000206 logger.Debugw("looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400207
208 if ips, err = net.LookupHost(host); err == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000209 logger.Debugw("dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400210 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000211 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400212 }
213 genmac = macifyIP(addr)
Shrey Baid807a2a02020-04-09 12:52:45 +0530214 logger.Debugw("using-ip-as-mac",
215 log.Fields{"host": ips[0],
216 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400217 return genmac, nil
218 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000219 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400220 }
221
222 genmac = macifyIP(addr)
Shrey Baid807a2a02020-04-09 12:52:45 +0530223 logger.Debugw("using-ip-as-mac",
224 log.Fields{"host": host,
225 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400226 return genmac, nil
227}
228
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530229func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700230 slist := strings.Split(mac, ":")
231 result := make([]uint32, len(slist))
232 var err error
233 var tmp int64
234 for index, val := range slist {
235 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
236 return []uint32{1, 2, 3, 4, 5, 6}
237 }
238 result[index] = uint32(tmp)
239 }
240 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530241}
242
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700243//GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800244func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530245
David K. Bainbridge794735f2020-02-11 21:01:37 -0800246 switch portType {
247 case voltha.Port_ETHERNET_NNI:
248 return fmt.Sprintf("nni-%d", portNum), nil
249 case voltha.Port_PON_OLT:
250 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700251 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800252
Girish Kumarf26e4882020-03-05 06:49:10 +0000253 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530254}
255
David K. Bainbridge794735f2020-02-11 21:01:37 -0800256func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000257 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700258 if state == "up" {
259 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500260 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500261 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700262 } else {
263 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500264 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700265 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700266 portNum := IntfIDToPortNo(intfID, portType)
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 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530299 logger.Debugw("sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700300 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700301 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000302 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800303 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000304 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400305 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530306 go dh.updateLocalDevice()
307 return nil
308}
309
310func (dh *DeviceHandler) updateLocalDevice() error {
311 dh.lockDevice.Lock()
312 defer dh.lockDevice.Unlock()
313 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
314 if err != nil || device == nil {
315 logger.Errorf("device", log.Fields{"device-id": dh.device.Id}, err)
316 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
317 }
318 dh.device = device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800319 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530320}
321
322// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800323func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000324 defer logger.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700325 defer func() {
326 dh.lockDevice.Lock()
327 dh.isReadIndicationRoutineActive = false
328 dh.lockDevice.Unlock()
329 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700330 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700331 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700332 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700333 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400334 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530335 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400336 if err != nil || device == nil {
337 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000338 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400339 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400340
David Bainbridgef5879ca2019-12-13 21:17:54 +0000341 // Create an exponential backoff around re-enabling indications. The
342 // maximum elapsed time for the back off is set to 0 so that we will
343 // continue to retry. The max interval defaults to 1m, but is set
344 // here for code clarity
345 indicationBackoff := backoff.NewExponentialBackOff()
346 indicationBackoff.MaxElapsedTime = 0
347 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700348
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700349 dh.lockDevice.Lock()
350 dh.isReadIndicationRoutineActive = true
351 dh.lockDevice.Unlock()
352
Girish Gowdra3f974912020-03-23 20:35:18 -0700353Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700354 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400355 select {
356 case <-dh.stopIndications:
Thomas Lee S985938d2020-05-04 11:40:41 +0530357 logger.Debugw("stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700358 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400359 default:
360 indication, err := indications.Recv()
361 if err == io.EOF {
Shrey Baid807a2a02020-04-09 12:52:45 +0530362 logger.Infow("eof-for-indications",
363 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530364 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400365 // Use an exponential back off to prevent getting into a tight loop
366 duration := indicationBackoff.NextBackOff()
367 if duration == backoff.Stop {
368 // If we reach a maximum then warn and reset the backoff
369 // timer and keep attempting.
Shrey Baid807a2a02020-04-09 12:52:45 +0530370 logger.Warnw("maximum-indication-backoff-reached--resetting-backoff-timer",
371 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530372 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400373 indicationBackoff.Reset()
374 }
375 time.Sleep(indicationBackoff.NextBackOff())
Girish Gowdra3f974912020-03-23 20:35:18 -0700376 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
377 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400378 }
379 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000380 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530381 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530382 logger.Errorw("read-indication-error",
383 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530384 "device-id": dh.device.Id})
385 if device.AdminState == voltha.AdminState_DELETED {
Shrey Baid807a2a02020-04-09 12:52:45 +0530386 logger.Debug("device-deleted--stopping-the-read-indication-thread")
Girish Gowdra3f974912020-03-23 20:35:18 -0700387 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400388 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700389 // Close the stream, and re-initialize it
390 if err = indications.CloseSend(); err != nil {
391 // Ok to ignore here, because we landed here due to a problem on the stream
392 // In all probability, the closeSend call may fail
Shrey Baid807a2a02020-04-09 12:52:45 +0530393 logger.Debugw("error-closing-send stream--error-ignored",
394 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530395 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700396 }
397 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
398 return err
399 }
400 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400401 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530402 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400403 // Reset backoff if we have a successful receive
404 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400405 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530406 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530407 logger.Debugw("olt-is-admin-down, ignore indication",
408 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530409 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400410 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400411 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400412 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700413 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700414 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700415 // Close the send stream
416 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700417
Girish Gowdra3f974912020-03-23 20:35:18 -0700418 return nil
419}
420
421func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
422
423 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
424 if err != nil {
425 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
426 }
427 if indications == nil {
428 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
429 }
430
431 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400432}
433
434// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
435func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
436 switch indication.Data.(type) {
437 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
438 return true
439
440 default:
441 return false
442 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700443}
444
David K. Bainbridge794735f2020-02-11 21:01:37 -0800445func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000446 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000447 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530448 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700449 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530450 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700451 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000452 // Send or clear Alarm
Thomas Lee S985938d2020-05-04 11:40:41 +0530453 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530454 return olterrors.NewErrAdapter("failed-indication", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530455 "device_id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800456 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000457 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800458 }
459 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700460}
461
David K. Bainbridge794735f2020-02-11 21:01:37 -0800462// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530463func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400464 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700465 switch indication.Data.(type) {
466 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800467 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530468 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800469 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700470 case *oop.Indication_IntfInd:
471 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800472 go func() {
473 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530474 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800475 }
476 }()
Thomas Lee S985938d2020-05-04 11:40:41 +0530477 logger.Infow("received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700478 case *oop.Indication_IntfOperInd:
479 intfOperInd := indication.GetIntfOperInd()
480 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 go func() {
482 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530483 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800484 }
485 }()
npujarec5762e2020-01-01 14:08:48 +0530486 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700487 } else if intfOperInd.GetType() == "pon" {
488 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
489 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800490 go func() {
491 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530492 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800493 }
494 }()
Thomas Lee S985938d2020-05-04 11:40:41 +0530495 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700496 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530497 logger.Infow("received-interface-oper-indication",
498 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530499 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700500 case *oop.Indication_OnuDiscInd:
501 onuDiscInd := indication.GetOnuDiscInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530502 logger.Infow("received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700503 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800504 go func() {
505 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530506 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800507 }
508 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700509 case *oop.Indication_OnuInd:
510 onuInd := indication.GetOnuInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530511 logger.Infow("received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800512 go func() {
513 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530514 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800515 }
516 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700517 case *oop.Indication_OmciInd:
518 omciInd := indication.GetOmciInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530519 logger.Debugw("received-omci-indication", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800520 go func() {
521 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530522 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800523 }
524 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525 case *oop.Indication_PktInd:
526 pktInd := indication.GetPktInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530527 logger.Infow("received-packet-indication", log.Fields{"PktInd": pktInd, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800528 go func() {
529 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530530 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800531 }
532 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700533 case *oop.Indication_PortStats:
534 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530535 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700536 case *oop.Indication_FlowStats:
537 flowStats := indication.GetFlowStats()
Thomas Lee S985938d2020-05-04 11:40:41 +0530538 logger.Infow("received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700539 case *oop.Indication_AlarmInd:
540 alarmInd := indication.GetAlarmInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530541 logger.Infow("received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
542 go dh.eventMgr.ProcessEvents(alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700543 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530544}
545
546// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530547func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530548 //starting the stat collector
549 go startCollector(dh)
550
Girish Gowdru0c588b22019-04-23 23:24:56 -0400551 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530552 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400553 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000554 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400555 }
556 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530557}
558
559// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530560func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700561 dh.lockDevice.Lock()
562 defer dh.lockDevice.Unlock()
Thomas Lee S985938d2020-05-04 11:40:41 +0530563 logger.Debugw("do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400564
npujarec5762e2020-01-01 14:08:48 +0530565 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400566 if err != nil || device == nil {
567 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000568 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400569 }
570
571 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400572
573 //Update the device oper state and connection status
574 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400575 dh.device = cloned
576
David K. Bainbridge794735f2020-02-11 21:01:37 -0800577 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000578 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400579 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400580
581 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530582 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400583 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000584 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400585 }
586 for _, onuDevice := range onuDevices.Items {
587
588 // Update onu state as down in onu adapter
589 onuInd := oop.OnuIndication{}
590 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800591 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700592 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800593 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530594 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800595 "source": "openolt",
596 "onu-indicator": onuInd,
597 "device-type": onuDevice.Type,
598 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700599 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700600 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400601 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700602 /* Discovered ONUs entries need to be cleared , since after OLT
603 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530604 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000605 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700606 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530607}
608
609// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530610func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400611 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800612 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530613 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530614 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000615 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400616 }
617 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530618}
619
620// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530621func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400622 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530623 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400624 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530625}
626
627// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530628func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530629 var err error
630 logger.Debugw("olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400631
632 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530633 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
634 if err != nil || device == nil {
635 /*TODO: needs to handle error scenarios */
636 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
637 }
638 if device.AdminState == voltha.AdminState_DISABLED {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000639 logger.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400640
641 cloned := proto.Clone(device).(*voltha.Device)
642 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
643 cloned.OperStatus = voltha.OperStatus_UNKNOWN
644 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530645 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
646 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400647 }
648
Chaitrashree G S44124192019-08-07 20:21:36 -0400649 // 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 +0530650 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400651 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530652 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400653 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400654 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
655 // all the modules initialized and ready to handle incoming ONUs.
656
Thomas Lee S985938d2020-05-04 11:40:41 +0530657 err = dh.initializeDeviceHandlerModules(ctx)
658 if err != nil {
659 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400660 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400661
662 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800663 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530664 if err = dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530665 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800666 }
667 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400668 return nil
669 }
670
Thomas Lee S985938d2020-05-04 11:40:41 +0530671 device, err = dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400672 if err != nil || device == nil {
673 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000674 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400675 }
kesavand39e0aa32020-01-28 20:58:50 -0500676 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500677 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000678 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400679 }
680
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400681 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530682 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400683 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530684
cuilin20187b2a8c32019-03-26 19:52:28 -0700685 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800686 go func() {
687 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530688 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800689 }
690 }()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530691 go dh.updateLocalDevice()
cuilin20187b2a8c32019-03-26 19:52:28 -0700692 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530693}
694
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400695func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
696 deviceInfo, err := dh.populateDeviceInfo()
697
698 if err != nil {
699 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
700 }
701 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
702 // Instantiate resource manager
Thomas Lee S985938d2020-05-04 11:40:41 +0530703 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.device.Id, KVStoreHostPort, dh.openOLT.KVStoreType, dh.device.Type, deviceInfo); dh.resourceMgr == nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400704 return olterrors.ErrResourceManagerInstantiating
705 }
706
707 // Instantiate flow manager
708 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
709 return olterrors.ErrResourceManagerInstantiating
710
711 }
712 /* TODO: Instantiate Alarm , stats , BW managers */
713 /* Instantiating Event Manager to handle Alarms and KPIs */
714 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
715
716 // Stats config for new device
717 dh.portStats = NewOpenOltStatsMgr(dh)
718
719 return nil
720
721}
722
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400723func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
724 var err error
725 var deviceInfo *oop.DeviceInfo
726
727 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
728
729 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000730 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400731 }
732 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000733 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400734 }
735
Thomas Lee S985938d2020-05-04 11:40:41 +0530736 logger.Debugw("fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400737 dh.device.Root = true
738 dh.device.Vendor = deviceInfo.Vendor
739 dh.device.Model = deviceInfo.Model
740 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
741 dh.device.HardwareVersion = deviceInfo.HardwareVersion
742 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
743
744 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000745 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400746 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
747 genmac, err := generateMacFromHost(host)
748 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000749 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400750 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000751 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400752 dh.device.MacAddress = genmac
753 } else {
754 dh.device.MacAddress = deviceInfo.DeviceId
755 }
756
757 // Synchronous call to update device - this method is run in its own go routine
758 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000759 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400760 }
761
762 return deviceInfo, nil
763}
764
Naga Manjunath7615e552019-10-11 22:35:47 +0530765func startCollector(dh *DeviceHandler) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530766 logger.Debugf("starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530767 context := make(map[string]string)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530768 freq := dh.metrics.ToPmConfigs().DefaultFreq
Naga Manjunath7615e552019-10-11 22:35:47 +0530769 for {
770 select {
771 case <-dh.stopCollector:
Thomas Lee S985938d2020-05-04 11:40:41 +0530772 logger.Debugw("stopping-collector-for-olt", log.Fields{"deviceID:": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530773 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530774 case <-time.After(time.Duration(freq) * time.Second):
Thomas Lee S985938d2020-05-04 11:40:41 +0530775 context["oltid"] = dh.device.Id
776 context["devicetype"] = dh.device.Type
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530777 ports := make([]*voltha.Port, len(dh.device.Ports))
778 copy(ports, dh.device.Ports)
779
780 for _, port := range ports {
781 // NNI Stats
782 if port.Type == voltha.Port_ETHERNET_NNI {
783 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
784 cmnni := dh.portStats.collectNNIMetrics(intfID)
785 logger.Debugw("collect-nni-metrics", log.Fields{"metrics": cmnni})
Thomas Lee S985938d2020-05-04 11:40:41 +0530786 go dh.portStats.publishMetrics(cmnni, port, context, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530787 logger.Debugw("publish-nni-metrics", log.Fields{"nni-port": port.Label})
788 }
789 // PON Stats
790 if port.Type == voltha.Port_PON_OLT {
791 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
792 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
793 cmpon := dh.portStats.collectPONMetrics(intfID)
794 logger.Debugw("collect-pon-metrics", log.Fields{"metrics": cmpon})
Thomas Lee S985938d2020-05-04 11:40:41 +0530795 go dh.portStats.publishMetrics(cmpon, port, context, dh.device.Id)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530796 }
797 logger.Debugw("publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500798 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530799 }
800 }
801 }
802}
803
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700804//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530805func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400806 dh.transitionMap = NewTransitionMap(dh)
Shrey Baid807a2a02020-04-09 12:52:45 +0530807 logger.Infow("adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530808 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530809
810 // Now, set the initial PM configuration for that device
811 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530812 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530813 }
814
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400815 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530816}
817
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530819func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700820 return &ic.SwitchCapability{
821 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530822 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700823 HwDesc: "open_pon",
824 SwDesc: "open_pon",
825 SerialNum: dh.device.SerialNumber,
826 },
827 SwitchFeatures: &of.OfpSwitchFeatures{
828 NBuffers: 256,
829 NTables: 2,
830 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
831 of.OfpCapabilities_OFPC_TABLE_STATS |
832 of.OfpCapabilities_OFPC_PORT_STATS |
833 of.OfpCapabilities_OFPC_GROUP_STATS),
834 },
835 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530836}
837
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700838//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530839func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700840 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700841 return &ic.PortCapability{
842 Port: &voltha.LogicalPort{
843 OfpPort: &of.OfpPort{
844 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
845 Config: 0,
846 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 Curr: capacity,
848 Advertised: capacity,
849 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700850 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
851 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
852 },
853 DeviceId: dh.device.Id,
854 DevicePortNo: uint32(portNo),
855 },
856 }, nil
857}
858
David K. Bainbridge794735f2020-02-11 21:01:37 -0800859func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530860 logger.Debugw("omci-indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700861 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700862 var deviceID string
863 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700864
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400865 transid := extractOmciTransactionID(omciInd.Pkt)
Thomas Lee S985938d2020-05-04 11:40:41 +0530866 logger.Debugw("recv-omci-msg", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id,
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400867 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
868
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700869 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530870
871 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
872
Thomas Lee S985938d2020-05-04 11:40:41 +0530873 logger.Debugw("omci-indication-for-a-device-not-in-cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700874 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700875 kwargs := make(map[string]interface{})
876 kwargs["onu_id"] = omciInd.OnuId
877 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700878
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700879 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
880 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530881 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800882 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000883 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700884 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700885 deviceType = onuDevice.Type
886 deviceID = onuDevice.Id
887 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
888 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530889 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700890 } else {
891 //found in cache
Thomas Lee S985938d2020-05-04 11:40:41 +0530892 logger.Debugw("omci-indication-for-a-device-in-cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530893 deviceType = onuInCache.(*OnuDevice).deviceType
894 deviceID = onuInCache.(*OnuDevice).deviceID
895 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700896 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700897
898 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800899 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Thomas Lee S985938d2020-05-04 11:40:41 +0530900 ic.InterAdapterMessageType_OMCI_REQUEST, dh.device.Type, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800901 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530902 return olterrors.NewErrCommunication("omci-request", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530903 "source": dh.device.Type,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800904 "destination": deviceType,
905 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000906 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700907 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800908 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530909}
910
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700911//ProcessInterAdapterMessage sends the proxied messages to the target device
912// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
913// is meant, and then send the unmarshalled omci message to this onu
914func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530915 logger.Debugw("process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700916 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700917 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700918 fromTopic := msg.Header.FromTopic
919 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700920 toDeviceID := msg.Header.ToDeviceId
921 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700922
Shrey Baid807a2a02020-04-09 12:52:45 +0530923 logger.Debugw("omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700924
925 msgBody := msg.GetBody()
926
927 omciMsg := &ic.InterAdapterOmciMessage{}
928 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000929 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700930 }
931
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700932 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700933 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
934 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530935 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800936 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000937 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700938 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530939 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 -0800940 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530941 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800942 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000943 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800944 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700945 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +0530946 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 -0800947 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530948 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800949 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000950 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800951 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700952 }
953
954 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000955 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700956 }
957 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530958}
959
David K. Bainbridge794735f2020-02-11 21:01:37 -0800960func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700961 var intfID uint32
962 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000963 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700964 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965 intfID = onuDevice.ProxyAddress.GetChannelId()
966 onuID = onuDevice.ProxyAddress.GetOnuId()
967 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700968 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700969 intfID = omciMsg.GetProxyAddress().GetChannelId()
970 onuID = omciMsg.GetProxyAddress().GetOnuId()
971 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700972 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700973 if connectStatus != voltha.ConnectStatus_REACHABLE {
Shrey Baid807a2a02020-04-09 12:52:45 +0530974 logger.Debugw("onu-not-reachable--cannot-send-omci", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800975
Thomas Lee S94109f12020-03-03 16:39:29 +0530976 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800977 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000978 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700979 }
980
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400981 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
982 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700983 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400984 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
985 hex.Encode(hexPkt, omciMsg.Message)
986 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
987
988 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
989 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
990 transid := extractOmciTransactionID(omciMsg.Message)
991 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
992 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700993
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700994 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
995 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530996 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800997 "interface-id": intfID,
998 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000999 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001000 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001001 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001002}
1003
David K. Bainbridge794735f2020-02-11 21:01:37 -08001004func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301005 logger.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001006 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
1007 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
1008 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001009 // TODO: need resource manager
1010 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001011 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301012 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001013 st, _ := status.FromError(err)
1014 if st.Code() == codes.AlreadyExists {
Thomas Lee S985938d2020-05-04 11:40:41 +05301015 logger.Debugw("onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onuID": onuID, "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001016 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301017 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001018 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001019 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301020 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001021 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001022 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001023}
1024
David K. Bainbridge794735f2020-02-11 21:01:37 -08001025func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001026
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001027 channelID := onuDiscInd.GetIntfId()
1028 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001029
Girish Kumar2ad402b2020-03-20 19:45:12 +00001030 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301031
cuilin20187b2a8c32019-03-26 19:52:28 -07001032 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001033 if sn != "" {
1034 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001035 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001036 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001037 }
1038
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301039 var alarmInd oop.OnuAlarmIndication
1040 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001041 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301042
1043 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1044 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1045 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1046 OnuLosRaise event sent for it */
1047 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1048 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1049 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Shrey Baid807a2a02020-04-09 12:52:45 +05301050 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301051 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1052 "currentIntfId": onuDiscInd.GetIntfId()})
1053 // TODO:: Should we need to ignore raising OnuLosClear event
1054 // when onu connected to different PON?
1055 }
1056 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1057 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1058 alarmInd.LosStatus = statusCheckOff
1059 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1060 }
1061 return true
1062 })
1063
Girish Kumar2ad402b2020-03-20 19:45:12 +00001064 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001066 }
1067
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001068 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001069
1070 // check the ONU is already know to the OLT
1071 // NOTE the second time the ONU is discovered this should return a device
1072 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1073
1074 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001075 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 -08001076 if e, ok := status.FromError(err); ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001077 logger.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001078 switch e.Code() {
1079 case codes.Internal:
1080 // this probably means NOT FOUND, so just create a new device
1081 onuDevice = nil
1082 case codes.DeadlineExceeded:
1083 // if the call times out, cleanup and exit
1084 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001085 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001086 }
1087 }
1088 }
1089
1090 if onuDevice == nil {
1091 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Girish Kumar2ad402b2020-03-20 19:45:12 +00001092 logger.Infow("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001093 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001094 ponintfid := onuDiscInd.GetIntfId()
1095 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301096 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001097 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001098
Girish Kumar2ad402b2020-03-20 19:45:12 +00001099 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001100
1101 if err != nil {
1102 // if we can't create an ID in resource manager,
1103 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001104 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001105 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001106 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001107 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001108 }
1109
1110 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1111 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001112 dh.discOnus.Delete(sn)
1113 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 +05301114 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001115 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001116 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001117 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001118 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Shrey Baid807a2a02020-04-09 12:52:45 +05301119 logger.Infow("onu-child-device-added",
1120 log.Fields{"onuDevice": onuDevice,
1121 "sn": sn,
1122 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301123 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001124 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001125
1126 // we can now use the existing ONU Id
1127 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001128 //Insert the ONU into cache to use in OnuIndication.
1129 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Shrey Baid807a2a02020-04-09 12:52:45 +05301130 logger.Debugw("onu-discovery-indication-key-create",
1131 log.Fields{"onuID": onuID,
1132 "intfId": onuDiscInd.GetIntfId(),
1133 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001134 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001135
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301136 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301137 dh.onus.Store(onuKey, onuDev)
Shrey Baid807a2a02020-04-09 12:52:45 +05301138 logger.Debugw("new-onu-device-discovered",
1139 log.Fields{"onu": onuDev,
1140 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001141
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301143 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001145 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001146 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301147 logger.Infow("onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301149 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001150 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001151 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001152 }
1153 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001154}
1155
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001157 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1158
1159 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001160 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001161 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001162 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001163 foundInCache := false
Shrey Baid807a2a02020-04-09 12:52:45 +05301164 logger.Debugw("onu-indication-key-create",
1165 log.Fields{"onuId": onuInd.OnuId,
1166 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301167 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001168 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301169
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 errFields := log.Fields{"device-id": dh.device.Id}
1171
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301172 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1173
Mahir Gunyele77977b2019-06-27 05:36:22 -07001174 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1175 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001176 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1177 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001178 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001179 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1180 if serialNumber != "" {
1181 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001182 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001183 } else {
1184 kwargs["onu_id"] = onuInd.OnuId
1185 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 errFields["onu-id"] = onuInd.OnuId
1187 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001188 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001189 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001190 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001191
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001193 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001194 }
1195
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 if onuDevice.ParentPortNo != ponPort {
Shrey Baid807a2a02020-04-09 12:52:45 +05301197 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001198 "previousIntfId": onuDevice.ParentPortNo,
1199 "currentIntfId": ponPort})
1200 }
1201
1202 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Shrey Baid807a2a02020-04-09 12:52:45 +05301203 logger.Warnw("onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
1204 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1205 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301206 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001207 }
1208 if !foundInCache {
1209 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1210
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301211 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 -08001212
1213 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001214 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001215 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001216 }
1217 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001218}
1219
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001220func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301221 ctx := context.TODO()
Shrey Baid807a2a02020-04-09 12:52:45 +05301222 logger.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001223 if onuInd.AdminState == "down" {
1224 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1225 if onuInd.OperState != "down" {
Shrey Baid807a2a02020-04-09 12:52:45 +05301226 logger.Warnw("onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001227 onuInd.OperState = "down"
1228 }
1229 }
1230
David K. Bainbridge794735f2020-02-11 21:01:37 -08001231 switch onuInd.OperState {
1232 case "down":
Shrey Baid807a2a02020-04-09 12:52:45 +05301233 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001234 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301235 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001236 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1237 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301238 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001239 "onu-indicator": onuInd,
1240 "source": "openolt",
1241 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001242 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001243 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 case "up":
Shrey Baid807a2a02020-04-09 12:52:45 +05301245 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Matt Jeanneret53539512019-07-20 14:47:02 -04001246 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301247 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001248 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1249 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301250 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 "onu-indicator": onuInd,
1252 "source": "openolt",
1253 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001254 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001255 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001257 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001258 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001259 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001260}
1261
cuilin20187b2a8c32019-03-26 19:52:28 -07001262func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1263 if serialNum != nil {
1264 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001265 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001266 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001267}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001268func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1269 decodedStr, err := hex.DecodeString(serialNum[4:])
1270 if err != nil {
1271 return nil, err
1272 }
1273 return &oop.SerialNumber{
1274 VendorId: []byte(serialNum[:4]),
1275 VendorSpecific: []byte(decodedStr),
1276 }, nil
1277}
cuilin20187b2a8c32019-03-26 19:52:28 -07001278
1279func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1280 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001281 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001282 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1283 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1284 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1285 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1286 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1287 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1288 return tmp
1289}
1290
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001291//UpdateFlowsBulk upates the bulk flow
1292func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301293 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001294}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001295
1296//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001297func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301298 logger.Debugw("getchilddevice",
1299 log.Fields{"pon-port": parentPort,
1300 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301301 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001302 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001304 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001305 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001306 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001307 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001309 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001310 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301311 logger.Debugw("successfully-received-child-device-from-core", log.Fields{"child-device-id": onuDevice.Id, "child-device-sn": onuDevice.SerialNumber})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001312 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301313}
1314
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001315// SendPacketInToCore sends packet-in to core
1316// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1317// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001318func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001319 logger.Debugw("send-packet-in-to-core", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301320 "port": logicalPort,
1321 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301322 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001323 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001324 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301325 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 "source": "adapter",
1327 "destination": "core",
1328 "device-id": dh.device.Id,
1329 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001330 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001331 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301332 logger.Debugw("sent-packet-in-to-core-successfully", log.Fields{
1333 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301334 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001335 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001336 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001337}
1338
A R Karthick1f85b802019-10-11 05:06:05 +00001339// AddUniPortToOnu adds the uni port to the onu device
1340func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1341 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301342
1343 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001344 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301345 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1346 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001347 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001348 }
1349 }
1350}
1351
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001352//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301353func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301354 logger.Debugw("received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001355
1356 var errorsList []error
1357
Girish Gowdru0c588b22019-04-23 23:24:56 -04001358 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001359 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001360 dh.incrementActiveFlowRemoveCount(flow)
1361
Shrey Baid807a2a02020-04-09 12:52:45 +05301362 logger.Debugw("removing-flow",
1363 log.Fields{"device-id": device.Id,
1364 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001365 err := dh.flowMgr.RemoveFlow(ctx, flow)
1366 if err != nil {
1367 errorsList = append(errorsList, err)
1368 }
1369
1370 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001371 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301372
1373 for _, flow := range flows.ToAdd.Items {
Shrey Baid807a2a02020-04-09 12:52:45 +05301374 logger.Debugw("adding-flow",
1375 log.Fields{"device-id": device.Id,
1376 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001377 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1378 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001379 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1380 if err != nil {
1381 errorsList = append(errorsList, err)
1382 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301383 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001384 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001385
Girish Gowdracefae192020-03-19 18:14:10 -07001386 // 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 +00001387 if groups != nil {
1388 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001389 err := dh.flowMgr.AddGroup(ctx, group)
1390 if err != nil {
1391 errorsList = append(errorsList, err)
1392 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001393 }
1394 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001395 err := dh.flowMgr.ModifyGroup(ctx, group)
1396 if err != nil {
1397 errorsList = append(errorsList, err)
1398 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001399 }
1400 if len(groups.ToRemove.Items) != 0 {
Thomas Lee S985938d2020-05-04 11:40:41 +05301401 logger.Debugw("group-delete-operation-not-supported", log.Fields{"device-id": dh.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001402 }
1403 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001404 if len(errorsList) > 0 {
1405 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1406 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301407 logger.Debugw("updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001408 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301409}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001410
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001411//DisableDevice disables the given device
1412//It marks the following for the given device:
1413//Device-Handler Admin-State : down
1414//Device Port-State: UNKNOWN
1415//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001416func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001417 /* On device disable ,admin state update has to be done prior sending request to agent since
1418 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001419 if dh.Client != nil {
1420 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1421 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001422 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001423 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001424 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001425 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301426 logger.Debugw("olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001427 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001428 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301429
1430 dh.discOnus = sync.Map{}
1431 dh.onus = sync.Map{}
1432
Thomas Lee S85f37312020-04-03 17:06:12 +05301433 //stopping the stats collector
1434 dh.stopCollector <- true
1435
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301436 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001437 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301438 //Update device Admin state
1439 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001440 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1441 for _, port := range cloned.Ports {
1442 if port.GetType() == voltha.Port_PON_OLT {
1443 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1444 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001445 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001446 }
1447 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001448 }
1449
Shrey Baid807a2a02020-04-09 12:52:45 +05301450 logger.Debugw("disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001451 return nil
1452}
1453
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301454func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001455
1456 // Update onu state as unreachable in onu adapter
1457 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301458 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001459 //get the child device for the parent device
1460 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1461 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301462 logger.Errorw("failed-to-get-child-devices-information", log.Fields{"device-id": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001463 }
1464 if onuDevices != nil {
1465 for _, onuDevice := range onuDevices.Items {
1466 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1467 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1468 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001469 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301470 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001471 }
1472
1473 }
1474 }
1475
1476}
1477
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001478//ReenableDevice re-enables the olt device after disable
1479//It marks the following for the given device:
1480//Device-Handler Admin-State : up
1481//Device Port-State: ACTIVE
1482//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001483func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301484
1485 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1486 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001487 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301488 }
1489 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001490 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001491
1492 cloned := proto.Clone(device).(*voltha.Device)
1493 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001494
kdarapu1afeceb2020-02-12 01:38:09 -05001495 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001496 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001497 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001498 //Update the device oper status as ACTIVE
1499 cloned.OperStatus = voltha.OperStatus_ACTIVE
1500 dh.device = cloned
1501
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001502 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301503 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001504 "device-id": device.Id,
1505 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001506 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001507 }
kesavand39e0aa32020-01-28 20:58:50 -05001508
Shrey Baid807a2a02020-04-09 12:52:45 +05301509 logger.Debugw("reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001510
1511 return nil
1512}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001513
npujarec5762e2020-01-01 14:08:48 +05301514func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001515 var uniID uint32
1516 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301517 for _, port := range onu.UniPorts {
1518 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001519 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001520 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301521 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301522 logger.Debugw("failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001523 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301524 logger.Debugw("deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301525 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001526 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301527 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001528 }
npujarec5762e2020-01-01 14:08:48 +05301529 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001530 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301531 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301532 logger.Debugw("failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001533 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301534 logger.Debugw("removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301535 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301536 logger.Debugw("failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001537 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301538 logger.Debugw("removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301539 }
npujarec5762e2020-01-01 14:08:48 +05301540 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1541 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301542 logger.Debugw("failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301543 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301544 logger.Debugw("removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301545 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301546 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 +00001547 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001548 }
1549 return nil
1550}
1551
npujarec5762e2020-01-01 14:08:48 +05301552func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001553 nniUniID := -1
1554 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301555
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001556 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301557 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001558 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001559 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301560 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301561 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001562 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001563 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301564 logger.Debugw("nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301565 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301566 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Shrey Baid807a2a02020-04-09 12:52:45 +05301567 logger.Debugw("current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301568 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301569 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301570 }
npujarec5762e2020-01-01 14:08:48 +05301571 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001572 }
npujarec5762e2020-01-01 14:08:48 +05301573 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001574 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301575 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001576 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001577}
1578
1579// 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 +05301580func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301581 logger.Debug("function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001582 /* Clear the KV store data associated with the all the UNI ports
1583 This clears up flow data and also resource map data for various
1584 other pon resources like alloc_id and gemport_id
1585 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001586 go dh.cleanupDeviceResources(ctx)
Shrey Baid807a2a02020-04-09 12:52:45 +05301587 logger.Debug("removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001588 // Stop the Stats collector
1589 dh.stopCollector <- true
1590 // stop the heartbeat check routine
1591 dh.stopHeartbeatCheck <- true
1592 //Reset the state
1593 if dh.Client != nil {
1594 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301595 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001596 }
1597 }
1598 cloned := proto.Clone(device).(*voltha.Device)
1599 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1600 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1601 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1602 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1603 "device-id": device.Id,
1604 "connect-status": cloned.ConnectStatus,
1605 "oper-status": cloned.OperStatus}, err).Log()
1606 }
1607 return nil
1608}
1609func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001610 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301611 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1612 var ponPort uint32
1613 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1614 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301615 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301616 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301617 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001618 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001619 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301620 }
1621 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301622 onuID := make([]uint32, 1)
Shrey Baid807a2a02020-04-09 12:52:45 +05301623 logger.Debugw("onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301624 if err = dh.clearUNIData(ctx, &onu); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301625 logger.Errorw("failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301626 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301627 // Clear flowids for gem cache.
1628 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301629 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301630 }
1631 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301632 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301633 }
npujarec5762e2020-01-01 14:08:48 +05301634 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301635 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301636 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301637 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301638 logger.Errorw("failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001639 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001640 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001641 /* Clear the flows from KV store associated with NNI port.
1642 There are mostly trap rules from NNI port (like LLDP)
1643 */
npujarec5762e2020-01-01 14:08:48 +05301644 if err := dh.clearNNIData(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301645 logger.Errorw("failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001646 }
A R Karthick1f85b802019-10-11 05:06:05 +00001647
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001648 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301649 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001650 }
A R Karthick1f85b802019-10-11 05:06:05 +00001651
Devmalya Paul495b94a2019-08-27 19:42:00 -04001652 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301653 dh.onus.Range(func(key interface{}, value interface{}) bool {
1654 dh.onus.Delete(key)
1655 return true
1656 })
1657
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001658 /*Delete discovered ONU map for the device*/
1659 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1660 dh.discOnus.Delete(key)
1661 return true
1662 })
1663
Devmalya Paul495b94a2019-08-27 19:42:00 -04001664 return nil
1665}
1666
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001667//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001668func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1669 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301670 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001671 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301672 logger.Debugw("rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001673 return nil
1674}
1675
David K. Bainbridge794735f2020-02-11 21:01:37 -08001676func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301677 logger.Debugw("received-packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001678 "packet-indication": *packetIn,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001679 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001680 "packet": hex.EncodeToString(packetIn.Pkt),
1681 })
npujarec5762e2020-01-01 14:08:48 +05301682 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001683 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001684 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001685 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301686 logger.Debugw("sending-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001687 "logicalPortNum": logicalPortNum,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001688 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001689 "packet": hex.EncodeToString(packetIn.Pkt),
1690 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001691 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301692 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001693 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301694 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001695 "device-id": dh.device.Id,
1696 "packet": hex.EncodeToString(packetIn.Pkt),
1697 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001698 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301699 logger.Debugw("success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001700 "packet": hex.EncodeToString(packetIn.Pkt),
Thomas Lee S985938d2020-05-04 11:40:41 +05301701 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001702 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001703 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001704}
1705
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001706// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301707func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001708 logger.Debugw("incoming-packet-out", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301709 "device-id": dh.device.Id,
Shrey Baid807a2a02020-04-09 12:52:45 +05301710 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001711 "pkt-length": len(packet.Data),
1712 "packet": hex.EncodeToString(packet.Data),
1713 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001714
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001715 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001716 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001717 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1718 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301719 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1720 // Do not packet-out lldp packets on uni port.
1721 // ONOS has no clue about uni/nni ports, it just packets out on all
1722 // available ports on the Logical Switch. It should not be interested
1723 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001724 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1725 "device-id": dh.device.Id,
1726 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301727 return nil
1728 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001729 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1730 if innerEthType == 0x8100 {
1731 // q-in-q 802.1ad or 802.1q double tagged packet.
1732 // slice out the outer tag.
1733 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001734 logger.Debugw("packet-now-single-tagged", log.Fields{
1735 "packetData": hex.EncodeToString(packet.Data),
1736 "device-id": dh.device.Id,
1737 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001738 }
1739 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001740 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1741 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001742 uniID := UniIDFromPortNum(uint32(egressPortNo))
1743
npujarec5762e2020-01-01 14:08:48 +05301744 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001745 if err != nil {
1746 // In this case the openolt agent will receive the gemPortID as 0.
1747 // The agent tries to retrieve the gemPortID in this case.
1748 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001749 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001750 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301751 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001752 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001753 }
1754
1755 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001756
Girish Kumar2ad402b2020-03-20 19:45:12 +00001757 logger.Debugw("sending-packet-to-onu", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301758 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001759 "IntfId": intfID,
1760 "onuID": onuID,
1761 "uniID": uniID,
1762 "gemPortID": gemPortID,
1763 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301764 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001765 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001766
npujarec5762e2020-01-01 14:08:48 +05301767 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301768 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001769 "source": "adapter",
1770 "destination": "onu",
1771 "egress-port-number": egressPortNo,
1772 "interface-id": intfID,
1773 "oni-id": onuID,
1774 "uni-id": uniID,
1775 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001776 "packet": hex.EncodeToString(packet.Data),
1777 "device-id": dh.device.Id,
1778 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001779 }
1780 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001781 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1782 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001783 return olterrors.NewErrInvalidValue(log.Fields{
1784 "egress-nni-port": egressPortNo,
1785 "device-id": dh.device.Id,
1786 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001787 }
1788 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001789
Girish Kumar2ad402b2020-03-20 19:45:12 +00001790 logger.Debugw("sending-packet-to-nni", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301791 "uplink-pkt": uplinkPkt,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001792 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301793 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001794 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001795
npujarec5762e2020-01-01 14:08:48 +05301796 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001797 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1798 "packet": hex.EncodeToString(packet.Data),
1799 "device-id": dh.device.Id,
1800 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001801 }
1802 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301803 logger.Warnw("packet-out-to-this-interface-type-not-implemented", log.Fields{
1804 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001805 "egressPortType": egressPortType,
1806 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301807 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001808 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001809 }
1810 return nil
1811}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001812
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001813func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1814 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001815}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301816
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001817func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301818 // start the heartbeat check towards the OLT.
1819 var timerCheck *time.Timer
1820
1821 for {
1822 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1823 select {
1824 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001825 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1826 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301827 logger.Warnw("hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301828 if timerCheck == nil {
1829 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001830 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301831 }
1832 } else {
1833 if timerCheck != nil {
1834 if timerCheck.Stop() {
Thomas Lee S985938d2020-05-04 11:40:41 +05301835 logger.Debugw("got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301836 }
1837 timerCheck = nil
1838 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301839 logger.Debugw("hearbeat",
1840 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301841 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301842 }
1843 cancel()
1844 case <-dh.stopHeartbeatCheck:
Thomas Lee S985938d2020-05-04 11:40:41 +05301845 logger.Debugw("stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301846 return
1847 }
1848 }
1849}
1850
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001851func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1852 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1853 if err != nil || device == nil {
1854 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1855 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301856
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001857 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1858 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1859 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1860 }
1861 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1862 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1863 }
1864 go dh.cleanupDeviceResources(ctx)
1865
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001866 dh.lockDevice.RLock()
1867 // Stop the read indication only if it the routine is active
1868 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1869 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1870 // on next execution of the readIndication routine.
1871 if dh.isReadIndicationRoutineActive {
1872 dh.stopIndications <- true
1873 }
1874 dh.lockDevice.RUnlock()
1875
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001876 dh.transitionMap.Handle(ctx, DeviceInit)
1877
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301878 }
1879}
kesavand39e0aa32020-01-28 20:58:50 -05001880
1881// EnablePort to enable Pon interface
1882func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001883 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001884 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001885}
1886
1887// DisablePort to disable pon interface
1888func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001889 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001890 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001891}
1892
kdarapu1afeceb2020-02-12 01:38:09 -05001893//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1894func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301895 ctx := context.Background()
Thomas Lee S985938d2020-05-04 11:40:41 +05301896 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05001897 if port.GetType() == voltha.Port_ETHERNET_NNI {
1898 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001899 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301900 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301901 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001902 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001903 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001904 }
1905 // fetch interfaceid from PortNo
1906 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1907 ponIntf := &oop.Interface{IntfId: ponID}
1908 var operStatus voltha.OperStatus_Types
1909 if enablePort {
1910 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301911 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001912
1913 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301914 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001915 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001916 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001917 }
1918 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001919 dh.activePorts.Store(ponID, true)
Shrey Baid807a2a02020-04-09 12:52:45 +05301920 logger.Infow("enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001921 } else {
1922 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301923 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001924 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301925 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001926 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001927 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001928 }
1929 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001930 dh.activePorts.Store(ponID, false)
Shrey Baid807a2a02020-04-09 12:52:45 +05301931 logger.Infow("disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001932 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301933 if err := dh.coreProxy.PortStateUpdate(ctx, dh.device.Id, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301934 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301935 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001936 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001937 }
1938 return nil
1939}
1940
kdarapu1afeceb2020-02-12 01:38:09 -05001941//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1942func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001943 cloned := proto.Clone(device).(*voltha.Device)
1944 // Disable the port and update the oper_port_status to core
1945 // if the Admin state of the port is disabled on reboot and re-enable device.
1946 for _, port := range cloned.Ports {
1947 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001948 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301949 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301950 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001951 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001952 }
1953 }
1954 }
1955 return nil
1956}
1957
1958//populateActivePorts to populate activePorts map
1959func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301960 logger.Infow("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001961 for _, port := range device.Ports {
1962 if port.Type == voltha.Port_ETHERNET_NNI {
1963 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001964 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001965 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001966 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001967 }
1968 }
1969 if port.Type == voltha.Port_PON_OLT {
1970 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001971 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001972 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001973 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001974 }
1975 }
1976 }
1977}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001978
1979// ChildDeviceLost deletes ONU and clears pon resources related to it.
1980func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001981 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001982 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1983 onuKey := dh.formOnuKey(IntfID, onuID)
1984 onuDevice, ok := dh.onus.Load(onuKey)
1985 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301986 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001987 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301988 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001989 "onu-id": onuID,
1990 "interface-id": IntfID}, nil).Log()
1991 }
1992 var sn *oop.SerialNumber
1993 var err error
1994 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301995 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001996 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301997 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001998 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1999 }
2000 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
2001 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302002 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302003 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002004 "onu-id": onuID}, err).Log()
2005 }
2006 //clear PON resources associated with ONU
2007 var onuGemData []rsrcMgr.OnuGemInfo
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002008 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[IntfID]; !ok {
2009 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302010 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002011 "interface-id": IntfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002012 } else {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002013 if err := onuMgr.GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05302014 logger.Warnw("failed-to-get-onu-info-for-pon-port", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302015 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002016 "interface-id": IntfID,
2017 "error": err})
2018 } else {
2019 for i, onu := range onuGemData {
2020 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Shrey Baid807a2a02020-04-09 12:52:45 +05302021 logger.Debugw("onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002022 if err := dh.clearUNIData(ctx, &onu); err != nil {
2023 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302024 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002025 "onu-device": onu,
2026 "error": err})
2027 }
2028 // Clear flowids for gem cache.
2029 for _, gem := range onu.GemPorts {
2030 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
2031 }
2032 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
2033 err := onuMgr.AddOnuGemInfo(ctx, IntfID, onuGemData)
2034 if err != nil {
2035 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
2036 "interface-id": IntfID,
2037 "onu-device": onu,
2038 "onu-gem": onuGemData,
2039 "error": err})
2040 //Not returning error on cleanup.
2041 }
2042 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": IntfID, "onu-device": onu, "onugem": onuGemData})
2043 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
2044 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002045 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002046 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002047 }
2048 }
2049 dh.onus.Delete(onuKey)
2050 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2051 return nil
2052}
Girish Gowdracefae192020-03-19 18:14:10 -07002053
2054func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2055 for _, field := range flows.GetOfbFields(flow) {
2056 if field.Type == flows.IN_PORT {
2057 return field.GetPort()
2058 }
2059 }
2060 return InvalidPort
2061}
2062
2063func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2064 for _, action := range flows.GetActions(flow) {
2065 if action.Type == flows.OUTPUT {
2066 if out := action.GetOutput(); out != nil {
2067 return out.GetPort()
2068 }
2069 }
2070 }
2071 return InvalidPort
2072}
2073
2074func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2075 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302076 logger.Debugw("increment-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002077 if inPort != InvalidPort && outPort != InvalidPort {
2078 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2079 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302080 logger.Debugw("increment-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002081
2082 dh.lockDevice.Lock()
2083 defer dh.lockDevice.Unlock()
2084 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2085 if !ok {
2086 flowRemoveData = pendingFlowRemoveData{
2087 pendingFlowRemoveCount: 0,
2088 allFlowsRemoved: make(chan struct{}),
2089 }
2090 }
2091 flowRemoveData.pendingFlowRemoveCount++
2092 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2093
Shrey Baid807a2a02020-04-09 12:52:45 +05302094 logger.Debugw("current-flow-remove-count–increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002095 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2096 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2097 }
2098}
2099
2100func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2101 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302102 logger.Debugw("decrement-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002103 if inPort != InvalidPort && outPort != InvalidPort {
2104 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2105 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302106 logger.Debugw("decrement-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002107
2108 dh.lockDevice.Lock()
2109 defer dh.lockDevice.Unlock()
2110 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302111 logger.Fatalf("flow-remove-key-not-found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002112 } else {
2113 if val.pendingFlowRemoveCount > 0 {
2114 val.pendingFlowRemoveCount--
2115 }
Shrey Baid807a2a02020-04-09 12:52:45 +05302116 logger.Debugw("current-flow-remove-count-after-decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002117 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2118 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2119 // If all flow removes have finished, then close the channel to signal the receiver
2120 // to go ahead with flow adds.
2121 if val.pendingFlowRemoveCount == 0 {
2122 close(val.allFlowsRemoved)
2123 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2124 return
2125 }
2126 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2127 }
2128 }
2129}
2130
2131func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2132 var flowRemoveData pendingFlowRemoveData
2133 var ok bool
2134 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302135 logger.Debugw("wait-for-flow-remove-to-finish-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002136 if inPort != InvalidPort && outPort != InvalidPort {
2137 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2138 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302139 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 -07002140
2141 dh.lockDevice.RLock()
2142 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302143 logger.Debugw("no-pending-flow-to-remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002144 dh.lockDevice.RUnlock()
2145 return
2146 }
2147 dh.lockDevice.RUnlock()
2148
2149 // Wait for all flow removes to finish first
2150 <-flowRemoveData.allFlowsRemoved
2151
Shrey Baid807a2a02020-04-09 12:52:45 +05302152 logger.Debugw("all-flows-cleared--handling-flow-add-now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002153 }
2154}
2155
2156func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2157 inPort := getInPortFromFlow(flow)
2158 outPort := getOutPortFromFlow(flow)
2159
2160 if inPort == InvalidPort || outPort == InvalidPort {
2161 return inPort, outPort
2162 }
2163
2164 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2165 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2166 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2167 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2168 return uniPort, outPort
2169 }
2170 }
2171 } else {
2172 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2173 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2174 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2175 return inPort, uniPort
2176 }
2177 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2178 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2179 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2180 return uniPort, outPort
2181 }
2182 }
2183 }
2184
2185 return InvalidPort, InvalidPort
2186}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002187
2188func extractOmciTransactionID(omciPkt []byte) uint16 {
2189 if len(omciPkt) > 3 {
2190 d := omciPkt[0:2]
2191 transid := binary.BigEndian.Uint16(d)
2192 return transid
2193 }
2194 return 0
2195}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002196
2197// StoreOnuDevice stores the onu parameters to the local cache.
2198func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2199 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2200 dh.onus.Store(onuKey, onuDevice)
2201}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002202
2203func (dh *DeviceHandler) getExtValue(device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
2204 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002205 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002206 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002207 resp := new(voltha.ReturnValues)
2208 valueparam := new(oop.ValueParam)
2209 ctx := context.Background()
2210 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002211 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2212 return nil, err
2213 }
2214 ID = device.ProxyAddress.GetOnuId()
2215 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2216 valueparam.Onu = &Onu
2217 valueparam.Value = value
2218
2219 // This API is unsupported until agent patch is added
2220 resp.Unsupported = uint32(value)
2221 _ = ctx
2222
2223 // Uncomment this code once agent changes are complete and tests
2224 /*
2225 resp, err = dh.Client.GetValue(ctx, valueparam)
2226 if err != nil {
2227 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2228 return nil, err
2229 }
2230 */
2231
2232 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2233 return resp, nil
2234}