blob: d6cb1e60b36265d040f01d2a4279230e364bcd74 [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" {
Girish Gowdra429f9502020-05-04 13:22:16 -07001224 // The ONU has gone admin_state "down" and we expect the ONU to send discovery again
1225 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001226 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1227 if onuInd.OperState != "down" {
Shrey Baid807a2a02020-04-09 12:52:45 +05301228 logger.Warnw("onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001229 onuInd.OperState = "down"
1230 }
1231 }
1232
David K. Bainbridge794735f2020-02-11 21:01:37 -08001233 switch onuInd.OperState {
1234 case "down":
Shrey Baid807a2a02020-04-09 12:52:45 +05301235 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 -07001236 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301237 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001238 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1239 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301240 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001241 "onu-indicator": onuInd,
1242 "source": "openolt",
1243 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001244 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001245 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001246 case "up":
Shrey Baid807a2a02020-04-09 12:52:45 +05301247 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 -04001248 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301249 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001250 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1251 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301252 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001253 "onu-indicator": onuInd,
1254 "source": "openolt",
1255 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001256 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001257 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001259 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001260 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001261 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001262}
1263
cuilin20187b2a8c32019-03-26 19:52:28 -07001264func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1265 if serialNum != nil {
1266 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001267 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001268 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001269}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001270func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1271 decodedStr, err := hex.DecodeString(serialNum[4:])
1272 if err != nil {
1273 return nil, err
1274 }
1275 return &oop.SerialNumber{
1276 VendorId: []byte(serialNum[:4]),
1277 VendorSpecific: []byte(decodedStr),
1278 }, nil
1279}
cuilin20187b2a8c32019-03-26 19:52:28 -07001280
1281func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1282 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001283 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001284 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1285 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1286 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1287 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1288 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1289 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1290 return tmp
1291}
1292
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001293//UpdateFlowsBulk upates the bulk flow
1294func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301295 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001296}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001297
1298//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001299func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301300 logger.Debugw("getchilddevice",
1301 log.Fields{"pon-port": parentPort,
1302 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301303 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001304 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001305 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001306 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001307 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001308 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001309 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001311 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001312 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301313 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 -08001314 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301315}
1316
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317// SendPacketInToCore sends packet-in to core
1318// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1319// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001320func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001321 logger.Debugw("send-packet-in-to-core", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301322 "port": logicalPort,
1323 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301324 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001325 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001326 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301327 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001328 "source": "adapter",
1329 "destination": "core",
1330 "device-id": dh.device.Id,
1331 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001332 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001333 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301334 logger.Debugw("sent-packet-in-to-core-successfully", log.Fields{
1335 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301336 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001337 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001339}
1340
A R Karthick1f85b802019-10-11 05:06:05 +00001341// AddUniPortToOnu adds the uni port to the onu device
1342func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1343 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301344
1345 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001346 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301347 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1348 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001349 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001350 }
1351 }
1352}
1353
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301355func (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 +05301356 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 +01001357
1358 var errorsList []error
1359
Girish Gowdru0c588b22019-04-23 23:24:56 -04001360 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001361 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001362 dh.incrementActiveFlowRemoveCount(flow)
1363
Shrey Baid807a2a02020-04-09 12:52:45 +05301364 logger.Debugw("removing-flow",
1365 log.Fields{"device-id": device.Id,
1366 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001367 err := dh.flowMgr.RemoveFlow(ctx, flow)
1368 if err != nil {
1369 errorsList = append(errorsList, err)
1370 }
1371
1372 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001373 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301374
1375 for _, flow := range flows.ToAdd.Items {
Shrey Baid807a2a02020-04-09 12:52:45 +05301376 logger.Debugw("adding-flow",
1377 log.Fields{"device-id": device.Id,
1378 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001379 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1380 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001381 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1382 if err != nil {
1383 errorsList = append(errorsList, err)
1384 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301385 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001386 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001387
Girish Gowdracefae192020-03-19 18:14:10 -07001388 // 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 +00001389 if groups != nil {
1390 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001391 err := dh.flowMgr.AddGroup(ctx, group)
1392 if err != nil {
1393 errorsList = append(errorsList, err)
1394 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001395 }
1396 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001397 err := dh.flowMgr.ModifyGroup(ctx, group)
1398 if err != nil {
1399 errorsList = append(errorsList, err)
1400 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001401 }
1402 if len(groups.ToRemove.Items) != 0 {
Thomas Lee S985938d2020-05-04 11:40:41 +05301403 logger.Debugw("group-delete-operation-not-supported", log.Fields{"device-id": dh.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001404 }
1405 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001406 if len(errorsList) > 0 {
1407 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1408 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301409 logger.Debugw("updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001410 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301411}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001412
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001413//DisableDevice disables the given device
1414//It marks the following for the given device:
1415//Device-Handler Admin-State : down
1416//Device Port-State: UNKNOWN
1417//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001418func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001419 /* On device disable ,admin state update has to be done prior sending request to agent since
1420 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001421 if dh.Client != nil {
1422 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1423 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001424 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001425 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001426 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001427 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301428 logger.Debugw("olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001429 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001430 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301431
1432 dh.discOnus = sync.Map{}
1433 dh.onus = sync.Map{}
1434
Thomas Lee S85f37312020-04-03 17:06:12 +05301435 //stopping the stats collector
1436 dh.stopCollector <- true
1437
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301438 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001439 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301440 //Update device Admin state
1441 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001442 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1443 for _, port := range cloned.Ports {
1444 if port.GetType() == voltha.Port_PON_OLT {
1445 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1446 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001447 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001448 }
1449 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001450 }
1451
Shrey Baid807a2a02020-04-09 12:52:45 +05301452 logger.Debugw("disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001453 return nil
1454}
1455
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301456func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001457
1458 // Update onu state as unreachable in onu adapter
1459 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301460 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001461 //get the child device for the parent device
1462 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1463 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301464 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 -04001465 }
1466 if onuDevices != nil {
1467 for _, onuDevice := range onuDevices.Items {
1468 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1469 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1470 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001471 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301472 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001473 }
1474
1475 }
1476 }
1477
1478}
1479
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001480//ReenableDevice re-enables the olt device after disable
1481//It marks the following for the given device:
1482//Device-Handler Admin-State : up
1483//Device Port-State: ACTIVE
1484//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001485func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301486
1487 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1488 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001489 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301490 }
1491 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001492 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001493
1494 cloned := proto.Clone(device).(*voltha.Device)
1495 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001496
kdarapu1afeceb2020-02-12 01:38:09 -05001497 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001498 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001499 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001500 //Update the device oper status as ACTIVE
1501 cloned.OperStatus = voltha.OperStatus_ACTIVE
1502 dh.device = cloned
1503
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001504 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301505 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001506 "device-id": device.Id,
1507 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001508 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001509 }
kesavand39e0aa32020-01-28 20:58:50 -05001510
Shrey Baid807a2a02020-04-09 12:52:45 +05301511 logger.Debugw("reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001512
1513 return nil
1514}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001515
npujarec5762e2020-01-01 14:08:48 +05301516func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001517 var uniID uint32
1518 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301519 for _, port := range onu.UniPorts {
1520 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001521 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001522 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301523 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301524 logger.Debugw("failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001525 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301526 logger.Debugw("deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301527 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001528 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301529 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001530 }
npujarec5762e2020-01-01 14:08:48 +05301531 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001532 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301533 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301534 logger.Debugw("failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001535 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301536 logger.Debugw("removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301537 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301538 logger.Debugw("failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001539 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301540 logger.Debugw("removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301541 }
npujarec5762e2020-01-01 14:08:48 +05301542 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1543 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301544 logger.Debugw("failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301545 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301546 logger.Debugw("removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301547 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301548 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 +00001549 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001550 }
1551 return nil
1552}
1553
npujarec5762e2020-01-01 14:08:48 +05301554func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001555 nniUniID := -1
1556 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301557
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001558 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301559 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001560 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001561 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301562 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301563 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001564 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001565 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301566 logger.Debugw("nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301567 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301568 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Shrey Baid807a2a02020-04-09 12:52:45 +05301569 logger.Debugw("current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301570 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301571 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301572 }
npujarec5762e2020-01-01 14:08:48 +05301573 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001574 }
npujarec5762e2020-01-01 14:08:48 +05301575 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001576 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301577 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001578 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001579}
1580
1581// 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 +05301582func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301583 logger.Debug("function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001584 /* Clear the KV store data associated with the all the UNI ports
1585 This clears up flow data and also resource map data for various
1586 other pon resources like alloc_id and gemport_id
1587 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001588 go dh.cleanupDeviceResources(ctx)
Shrey Baid807a2a02020-04-09 12:52:45 +05301589 logger.Debug("removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001590 // Stop the Stats collector
1591 dh.stopCollector <- true
1592 // stop the heartbeat check routine
1593 dh.stopHeartbeatCheck <- true
1594 //Reset the state
1595 if dh.Client != nil {
1596 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301597 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001598 }
1599 }
1600 cloned := proto.Clone(device).(*voltha.Device)
1601 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1602 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1603 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1604 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1605 "device-id": device.Id,
1606 "connect-status": cloned.ConnectStatus,
1607 "oper-status": cloned.OperStatus}, err).Log()
1608 }
1609 return nil
1610}
1611func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001612 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301613 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1614 var ponPort uint32
1615 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1616 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301617 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301618 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301619 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001620 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001621 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301622 }
1623 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301624 onuID := make([]uint32, 1)
Shrey Baid807a2a02020-04-09 12:52:45 +05301625 logger.Debugw("onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301626 if err = dh.clearUNIData(ctx, &onu); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301627 logger.Errorw("failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301628 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301629 // Clear flowids for gem cache.
1630 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301631 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301632 }
1633 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301634 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301635 }
npujarec5762e2020-01-01 14:08:48 +05301636 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301637 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301638 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301639 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301640 logger.Errorw("failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001641 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001642 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001643 /* Clear the flows from KV store associated with NNI port.
1644 There are mostly trap rules from NNI port (like LLDP)
1645 */
npujarec5762e2020-01-01 14:08:48 +05301646 if err := dh.clearNNIData(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301647 logger.Errorw("failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001648 }
A R Karthick1f85b802019-10-11 05:06:05 +00001649
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001650 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301651 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001652 }
A R Karthick1f85b802019-10-11 05:06:05 +00001653
Devmalya Paul495b94a2019-08-27 19:42:00 -04001654 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301655 dh.onus.Range(func(key interface{}, value interface{}) bool {
1656 dh.onus.Delete(key)
1657 return true
1658 })
1659
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001660 /*Delete discovered ONU map for the device*/
1661 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1662 dh.discOnus.Delete(key)
1663 return true
1664 })
1665
Devmalya Paul495b94a2019-08-27 19:42:00 -04001666 return nil
1667}
1668
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001669//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001670func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1671 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301672 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001673 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301674 logger.Debugw("rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001675 return nil
1676}
1677
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301679 logger.Debugw("received-packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001680 "packet-indication": *packetIn,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001681 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001682 "packet": hex.EncodeToString(packetIn.Pkt),
1683 })
npujarec5762e2020-01-01 14:08:48 +05301684 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001685 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001686 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001687 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301688 logger.Debugw("sending-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001689 "logicalPortNum": logicalPortNum,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001690 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001691 "packet": hex.EncodeToString(packetIn.Pkt),
1692 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001693 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301694 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001695 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301696 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001697 "device-id": dh.device.Id,
1698 "packet": hex.EncodeToString(packetIn.Pkt),
1699 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001700 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301701 logger.Debugw("success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001702 "packet": hex.EncodeToString(packetIn.Pkt),
Thomas Lee S985938d2020-05-04 11:40:41 +05301703 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001704 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001705 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001706}
1707
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001708// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301709func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001710 logger.Debugw("incoming-packet-out", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301711 "device-id": dh.device.Id,
Shrey Baid807a2a02020-04-09 12:52:45 +05301712 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001713 "pkt-length": len(packet.Data),
1714 "packet": hex.EncodeToString(packet.Data),
1715 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001716
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001717 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001718 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001719 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1720 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301721 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1722 // Do not packet-out lldp packets on uni port.
1723 // ONOS has no clue about uni/nni ports, it just packets out on all
1724 // available ports on the Logical Switch. It should not be interested
1725 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001726 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1727 "device-id": dh.device.Id,
1728 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301729 return nil
1730 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001731 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1732 if innerEthType == 0x8100 {
1733 // q-in-q 802.1ad or 802.1q double tagged packet.
1734 // slice out the outer tag.
1735 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001736 logger.Debugw("packet-now-single-tagged", log.Fields{
1737 "packetData": hex.EncodeToString(packet.Data),
1738 "device-id": dh.device.Id,
1739 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001740 }
1741 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001742 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1743 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001744 uniID := UniIDFromPortNum(uint32(egressPortNo))
1745
npujarec5762e2020-01-01 14:08:48 +05301746 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001747 if err != nil {
1748 // In this case the openolt agent will receive the gemPortID as 0.
1749 // The agent tries to retrieve the gemPortID in this case.
1750 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001751 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001752 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301753 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001754 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001755 }
1756
1757 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001758
Girish Kumar2ad402b2020-03-20 19:45:12 +00001759 logger.Debugw("sending-packet-to-onu", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301760 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001761 "IntfId": intfID,
1762 "onuID": onuID,
1763 "uniID": uniID,
1764 "gemPortID": gemPortID,
1765 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301766 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001767 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001768
npujarec5762e2020-01-01 14:08:48 +05301769 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301770 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001771 "source": "adapter",
1772 "destination": "onu",
1773 "egress-port-number": egressPortNo,
1774 "interface-id": intfID,
1775 "oni-id": onuID,
1776 "uni-id": uniID,
1777 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001778 "packet": hex.EncodeToString(packet.Data),
1779 "device-id": dh.device.Id,
1780 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001781 }
1782 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001783 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1784 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001785 return olterrors.NewErrInvalidValue(log.Fields{
1786 "egress-nni-port": egressPortNo,
1787 "device-id": dh.device.Id,
1788 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001789 }
1790 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001791
Girish Kumar2ad402b2020-03-20 19:45:12 +00001792 logger.Debugw("sending-packet-to-nni", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301793 "uplink-pkt": uplinkPkt,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001794 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301795 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001796 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001797
npujarec5762e2020-01-01 14:08:48 +05301798 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001799 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1800 "packet": hex.EncodeToString(packet.Data),
1801 "device-id": dh.device.Id,
1802 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001803 }
1804 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301805 logger.Warnw("packet-out-to-this-interface-type-not-implemented", log.Fields{
1806 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001807 "egressPortType": egressPortType,
1808 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301809 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001810 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001811 }
1812 return nil
1813}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001814
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001815func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1816 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001817}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301818
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001819func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301820 // start the heartbeat check towards the OLT.
1821 var timerCheck *time.Timer
1822
1823 for {
1824 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1825 select {
1826 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001827 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1828 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301829 logger.Warnw("hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301830 if timerCheck == nil {
1831 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001832 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301833 }
1834 } else {
1835 if timerCheck != nil {
1836 if timerCheck.Stop() {
Thomas Lee S985938d2020-05-04 11:40:41 +05301837 logger.Debugw("got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301838 }
1839 timerCheck = nil
1840 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301841 logger.Debugw("hearbeat",
1842 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301843 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301844 }
1845 cancel()
1846 case <-dh.stopHeartbeatCheck:
Thomas Lee S985938d2020-05-04 11:40:41 +05301847 logger.Debugw("stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301848 return
1849 }
1850 }
1851}
1852
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001853func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1854 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1855 if err != nil || device == nil {
1856 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1857 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301858
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001859 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1860 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1861 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1862 }
1863 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1864 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1865 }
1866 go dh.cleanupDeviceResources(ctx)
1867
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001868 dh.lockDevice.RLock()
1869 // Stop the read indication only if it the routine is active
1870 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1871 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1872 // on next execution of the readIndication routine.
1873 if dh.isReadIndicationRoutineActive {
1874 dh.stopIndications <- true
1875 }
1876 dh.lockDevice.RUnlock()
1877
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001878 dh.transitionMap.Handle(ctx, DeviceInit)
1879
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301880 }
1881}
kesavand39e0aa32020-01-28 20:58:50 -05001882
1883// EnablePort to enable Pon interface
1884func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001885 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001886 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001887}
1888
1889// DisablePort to disable pon interface
1890func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001891 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001892 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001893}
1894
kdarapu1afeceb2020-02-12 01:38:09 -05001895//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1896func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301897 ctx := context.Background()
Thomas Lee S985938d2020-05-04 11:40:41 +05301898 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05001899 if port.GetType() == voltha.Port_ETHERNET_NNI {
1900 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001901 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301902 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301903 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001904 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001905 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001906 }
1907 // fetch interfaceid from PortNo
1908 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1909 ponIntf := &oop.Interface{IntfId: ponID}
1910 var operStatus voltha.OperStatus_Types
1911 if enablePort {
1912 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301913 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001914
1915 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301916 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001917 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001918 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001919 }
1920 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001921 dh.activePorts.Store(ponID, true)
Shrey Baid807a2a02020-04-09 12:52:45 +05301922 logger.Infow("enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001923 } else {
1924 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301925 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001926 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301927 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001928 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001929 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001930 }
1931 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001932 dh.activePorts.Store(ponID, false)
Shrey Baid807a2a02020-04-09 12:52:45 +05301933 logger.Infow("disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001934 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301935 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 +05301936 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301937 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001938 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001939 }
1940 return nil
1941}
1942
kdarapu1afeceb2020-02-12 01:38:09 -05001943//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1944func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001945 cloned := proto.Clone(device).(*voltha.Device)
1946 // Disable the port and update the oper_port_status to core
1947 // if the Admin state of the port is disabled on reboot and re-enable device.
1948 for _, port := range cloned.Ports {
1949 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001950 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301951 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301952 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001953 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001954 }
1955 }
1956 }
1957 return nil
1958}
1959
1960//populateActivePorts to populate activePorts map
1961func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301962 logger.Infow("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001963 for _, port := range device.Ports {
1964 if port.Type == voltha.Port_ETHERNET_NNI {
1965 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001966 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001967 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001968 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001969 }
1970 }
1971 if port.Type == voltha.Port_PON_OLT {
1972 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001973 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001974 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001975 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001976 }
1977 }
1978 }
1979}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001980
1981// ChildDeviceLost deletes ONU and clears pon resources related to it.
1982func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001983 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001984 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1985 onuKey := dh.formOnuKey(IntfID, onuID)
1986 onuDevice, ok := dh.onus.Load(onuKey)
1987 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301988 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001989 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301990 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001991 "onu-id": onuID,
1992 "interface-id": IntfID}, nil).Log()
1993 }
1994 var sn *oop.SerialNumber
1995 var err error
1996 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301997 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001998 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301999 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002000 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2001 }
2002 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
2003 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302004 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302005 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002006 "onu-id": onuID}, err).Log()
2007 }
2008 //clear PON resources associated with ONU
2009 var onuGemData []rsrcMgr.OnuGemInfo
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002010 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[IntfID]; !ok {
2011 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302012 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002013 "interface-id": IntfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002014 } else {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002015 if err := onuMgr.GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05302016 logger.Warnw("failed-to-get-onu-info-for-pon-port", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302017 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002018 "interface-id": IntfID,
2019 "error": err})
2020 } else {
2021 for i, onu := range onuGemData {
2022 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Shrey Baid807a2a02020-04-09 12:52:45 +05302023 logger.Debugw("onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002024 if err := dh.clearUNIData(ctx, &onu); err != nil {
2025 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302026 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002027 "onu-device": onu,
2028 "error": err})
2029 }
2030 // Clear flowids for gem cache.
2031 for _, gem := range onu.GemPorts {
2032 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
2033 }
2034 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
2035 err := onuMgr.AddOnuGemInfo(ctx, IntfID, onuGemData)
2036 if err != nil {
2037 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
2038 "interface-id": IntfID,
2039 "onu-device": onu,
2040 "onu-gem": onuGemData,
2041 "error": err})
2042 //Not returning error on cleanup.
2043 }
2044 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": IntfID, "onu-device": onu, "onugem": onuGemData})
2045 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
2046 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002047 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002048 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002049 }
2050 }
2051 dh.onus.Delete(onuKey)
2052 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2053 return nil
2054}
Girish Gowdracefae192020-03-19 18:14:10 -07002055
2056func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2057 for _, field := range flows.GetOfbFields(flow) {
2058 if field.Type == flows.IN_PORT {
2059 return field.GetPort()
2060 }
2061 }
2062 return InvalidPort
2063}
2064
2065func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2066 for _, action := range flows.GetActions(flow) {
2067 if action.Type == flows.OUTPUT {
2068 if out := action.GetOutput(); out != nil {
2069 return out.GetPort()
2070 }
2071 }
2072 }
2073 return InvalidPort
2074}
2075
2076func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2077 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302078 logger.Debugw("increment-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002079 if inPort != InvalidPort && outPort != InvalidPort {
2080 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2081 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302082 logger.Debugw("increment-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002083
2084 dh.lockDevice.Lock()
2085 defer dh.lockDevice.Unlock()
2086 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2087 if !ok {
2088 flowRemoveData = pendingFlowRemoveData{
2089 pendingFlowRemoveCount: 0,
2090 allFlowsRemoved: make(chan struct{}),
2091 }
2092 }
2093 flowRemoveData.pendingFlowRemoveCount++
2094 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2095
Shrey Baid807a2a02020-04-09 12:52:45 +05302096 logger.Debugw("current-flow-remove-count–increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002097 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2098 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2099 }
2100}
2101
2102func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2103 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302104 logger.Debugw("decrement-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002105 if inPort != InvalidPort && outPort != InvalidPort {
2106 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2107 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302108 logger.Debugw("decrement-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002109
2110 dh.lockDevice.Lock()
2111 defer dh.lockDevice.Unlock()
2112 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302113 logger.Fatalf("flow-remove-key-not-found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002114 } else {
2115 if val.pendingFlowRemoveCount > 0 {
2116 val.pendingFlowRemoveCount--
2117 }
Shrey Baid807a2a02020-04-09 12:52:45 +05302118 logger.Debugw("current-flow-remove-count-after-decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002119 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2120 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2121 // If all flow removes have finished, then close the channel to signal the receiver
2122 // to go ahead with flow adds.
2123 if val.pendingFlowRemoveCount == 0 {
2124 close(val.allFlowsRemoved)
2125 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2126 return
2127 }
2128 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2129 }
2130 }
2131}
2132
2133func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2134 var flowRemoveData pendingFlowRemoveData
2135 var ok bool
2136 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302137 logger.Debugw("wait-for-flow-remove-to-finish-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002138 if inPort != InvalidPort && outPort != InvalidPort {
2139 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2140 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302141 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 -07002142
2143 dh.lockDevice.RLock()
2144 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302145 logger.Debugw("no-pending-flow-to-remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002146 dh.lockDevice.RUnlock()
2147 return
2148 }
2149 dh.lockDevice.RUnlock()
2150
2151 // Wait for all flow removes to finish first
2152 <-flowRemoveData.allFlowsRemoved
2153
Shrey Baid807a2a02020-04-09 12:52:45 +05302154 logger.Debugw("all-flows-cleared--handling-flow-add-now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002155 }
2156}
2157
2158func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2159 inPort := getInPortFromFlow(flow)
2160 outPort := getOutPortFromFlow(flow)
2161
2162 if inPort == InvalidPort || outPort == InvalidPort {
2163 return inPort, outPort
2164 }
2165
2166 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2167 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2168 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2169 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2170 return uniPort, outPort
2171 }
2172 }
2173 } else {
2174 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2175 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2176 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2177 return inPort, uniPort
2178 }
2179 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2180 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2181 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2182 return uniPort, outPort
2183 }
2184 }
2185 }
2186
2187 return InvalidPort, InvalidPort
2188}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002189
2190func extractOmciTransactionID(omciPkt []byte) uint16 {
2191 if len(omciPkt) > 3 {
2192 d := omciPkt[0:2]
2193 transid := binary.BigEndian.Uint16(d)
2194 return transid
2195 }
2196 return 0
2197}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002198
2199// StoreOnuDevice stores the onu parameters to the local cache.
2200func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2201 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2202 dh.onus.Store(onuKey, onuDevice)
2203}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002204
2205func (dh *DeviceHandler) getExtValue(device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
2206 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002207 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002208 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002209 resp := new(voltha.ReturnValues)
2210 valueparam := new(oop.ValueParam)
2211 ctx := context.Background()
2212 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002213 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2214 return nil, err
2215 }
2216 ID = device.ProxyAddress.GetOnuId()
2217 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2218 valueparam.Onu = &Onu
2219 valueparam.Value = value
2220
2221 // This API is unsupported until agent patch is added
2222 resp.Unsupported = uint32(value)
2223 _ = ctx
2224
2225 // Uncomment this code once agent changes are complete and tests
2226 /*
2227 resp, err = dh.Client.GetValue(ctx, valueparam)
2228 if err != nil {
2229 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2230 return nil, err
2231 }
2232 */
2233
2234 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2235 return resp, nil
2236}