blob: a008e656c773580777afbf836b93d26ea3452937 [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)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400267 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800268 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000269 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400270 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500271
272 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
273 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000274 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500275 }
276 if device.Ports != nil {
277 for _, dPort := range device.Ports {
278 if dPort.Type == portType && dPort.PortNo == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000279 logger.Debug("port-already-exists-updating-oper-status-of-port")
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500280 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530281 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800282 "device-id": dh.device.Id,
283 "port-type": portType,
284 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000285 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800286
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500287 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800288 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500289 }
290 }
291 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400292 // Now create Port
293 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700294 PortNo: portNum,
295 Label: label,
296 Type: portType,
297 OperStatus: operStatus,
298 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530299 logger.Debugw("sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700300 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700301 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000302 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800303 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000304 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400305 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530306 go dh.updateLocalDevice()
307 return nil
308}
309
310func (dh *DeviceHandler) updateLocalDevice() error {
311 dh.lockDevice.Lock()
312 defer dh.lockDevice.Unlock()
313 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
314 if err != nil || device == nil {
315 logger.Errorf("device", log.Fields{"device-id": dh.device.Id}, err)
316 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
317 }
318 dh.device = device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800319 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530320}
321
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")
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530767 freq := dh.metrics.ToPmConfigs().DefaultFreq
Naga Manjunath7615e552019-10-11 22:35:47 +0530768 for {
769 select {
770 case <-dh.stopCollector:
Thomas Lee S985938d2020-05-04 11:40:41 +0530771 logger.Debugw("stopping-collector-for-olt", log.Fields{"deviceID:": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530772 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530773 case <-time.After(time.Duration(freq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700774
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530775 ports := make([]*voltha.Port, len(dh.device.Ports))
776 copy(ports, dh.device.Ports)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530777 for _, port := range ports {
778 // NNI Stats
779 if port.Type == voltha.Port_ETHERNET_NNI {
780 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
781 cmnni := dh.portStats.collectNNIMetrics(intfID)
782 logger.Debugw("collect-nni-metrics", log.Fields{"metrics": cmnni})
Girish Gowdra34815db2020-05-11 17:18:04 -0700783 go dh.portStats.publishMetrics(cmnni, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530784 logger.Debugw("publish-nni-metrics", log.Fields{"nni-port": port.Label})
785 }
786 // PON Stats
787 if port.Type == voltha.Port_PON_OLT {
788 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
789 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
790 cmpon := dh.portStats.collectPONMetrics(intfID)
791 logger.Debugw("collect-pon-metrics", log.Fields{"metrics": cmpon})
Girish Gowdra34815db2020-05-11 17:18:04 -0700792 go dh.portStats.publishMetrics(cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530793 }
794 logger.Debugw("publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500795 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530796 }
797 }
798 }
799}
800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700801//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530802func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400803 dh.transitionMap = NewTransitionMap(dh)
Shrey Baid807a2a02020-04-09 12:52:45 +0530804 logger.Infow("adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530805 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530806
807 // Now, set the initial PM configuration for that device
808 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530809 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530810 }
811
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400812 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530813}
814
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700815//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530816func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700817 return &ic.SwitchCapability{
818 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530819 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700820 HwDesc: "open_pon",
821 SwDesc: "open_pon",
822 SerialNum: dh.device.SerialNumber,
823 },
824 SwitchFeatures: &of.OfpSwitchFeatures{
825 NBuffers: 256,
826 NTables: 2,
827 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
828 of.OfpCapabilities_OFPC_TABLE_STATS |
829 of.OfpCapabilities_OFPC_PORT_STATS |
830 of.OfpCapabilities_OFPC_GROUP_STATS),
831 },
832 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530833}
834
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700835//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530836func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700837 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700838 return &ic.PortCapability{
839 Port: &voltha.LogicalPort{
840 OfpPort: &of.OfpPort{
841 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
842 Config: 0,
843 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700844 Curr: capacity,
845 Advertised: capacity,
846 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700847 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
848 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
849 },
850 DeviceId: dh.device.Id,
851 DevicePortNo: uint32(portNo),
852 },
853 }, nil
854}
855
David K. Bainbridge794735f2020-02-11 21:01:37 -0800856func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530857 logger.Debugw("omci-indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700858 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700859 var deviceID string
860 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700861
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400862 transid := extractOmciTransactionID(omciInd.Pkt)
Thomas Lee S985938d2020-05-04 11:40:41 +0530863 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 -0400864 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
865
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700866 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530867
868 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
869
Thomas Lee S985938d2020-05-04 11:40:41 +0530870 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 -0700871 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700872 kwargs := make(map[string]interface{})
873 kwargs["onu_id"] = omciInd.OnuId
874 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700875
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700876 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
877 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530878 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800879 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000880 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700881 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700882 deviceType = onuDevice.Type
883 deviceID = onuDevice.Id
884 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
885 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530886 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700887 } else {
888 //found in cache
Thomas Lee S985938d2020-05-04 11:40:41 +0530889 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 +0530890 deviceType = onuInCache.(*OnuDevice).deviceType
891 deviceID = onuInCache.(*OnuDevice).deviceID
892 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700893 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700894
895 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800896 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Thomas Lee S985938d2020-05-04 11:40:41 +0530897 ic.InterAdapterMessageType_OMCI_REQUEST, dh.device.Type, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800898 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530899 return olterrors.NewErrCommunication("omci-request", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530900 "source": dh.device.Type,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800901 "destination": deviceType,
902 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000903 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700904 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800905 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530906}
907
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700908//ProcessInterAdapterMessage sends the proxied messages to the target device
909// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
910// is meant, and then send the unmarshalled omci message to this onu
911func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530912 logger.Debugw("process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700913 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700914 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700915 fromTopic := msg.Header.FromTopic
916 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700917 toDeviceID := msg.Header.ToDeviceId
918 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700919
Shrey Baid807a2a02020-04-09 12:52:45 +0530920 logger.Debugw("omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700921
922 msgBody := msg.GetBody()
923
924 omciMsg := &ic.InterAdapterOmciMessage{}
925 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000926 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700927 }
928
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700929 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700930 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
931 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530932 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800933 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000934 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700935 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530936 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 -0800937 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530938 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800939 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000940 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800941 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700942 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +0530943 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 -0800944 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530945 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800946 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000947 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800948 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700949 }
950
951 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000952 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700953 }
954 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530955}
956
David K. Bainbridge794735f2020-02-11 21:01:37 -0800957func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700958 var intfID uint32
959 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000960 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700961 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700962 intfID = onuDevice.ProxyAddress.GetChannelId()
963 onuID = onuDevice.ProxyAddress.GetOnuId()
964 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700965 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700966 intfID = omciMsg.GetProxyAddress().GetChannelId()
967 onuID = omciMsg.GetProxyAddress().GetOnuId()
968 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700969 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700970 if connectStatus != voltha.ConnectStatus_REACHABLE {
Shrey Baid807a2a02020-04-09 12:52:45 +0530971 logger.Debugw("onu-not-reachable--cannot-send-omci", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800972
Thomas Lee S94109f12020-03-03 16:39:29 +0530973 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800974 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000975 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700976 }
977
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400978 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
979 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700980 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400981 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
982 hex.Encode(hexPkt, omciMsg.Message)
983 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
984
985 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
986 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
987 transid := extractOmciTransactionID(omciMsg.Message)
988 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
989 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700990
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700991 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
992 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530993 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800994 "interface-id": intfID,
995 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000996 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700997 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800998 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700999}
1000
David K. Bainbridge794735f2020-02-11 21:01:37 -08001001func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301002 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 +02001003 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
1004 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
1005 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001006 // TODO: need resource manager
1007 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001008 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301009 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001010 st, _ := status.FromError(err)
1011 if st.Code() == codes.AlreadyExists {
Thomas Lee S985938d2020-05-04 11:40:41 +05301012 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 -04001013 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301014 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001015 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001016 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301017 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001018 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001019 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001020}
1021
David K. Bainbridge794735f2020-02-11 21:01:37 -08001022func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001023
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001024 channelID := onuDiscInd.GetIntfId()
1025 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001026
Girish Kumar2ad402b2020-03-20 19:45:12 +00001027 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301028
cuilin20187b2a8c32019-03-26 19:52:28 -07001029 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001030 if sn != "" {
1031 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001032 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001033 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001034 }
1035
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301036 var alarmInd oop.OnuAlarmIndication
1037 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001038 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301039
1040 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1041 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1042 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1043 OnuLosRaise event sent for it */
1044 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1045 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1046 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Shrey Baid807a2a02020-04-09 12:52:45 +05301047 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301048 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1049 "currentIntfId": onuDiscInd.GetIntfId()})
1050 // TODO:: Should we need to ignore raising OnuLosClear event
1051 // when onu connected to different PON?
1052 }
1053 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1054 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1055 alarmInd.LosStatus = statusCheckOff
1056 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1057 }
1058 return true
1059 })
1060
Girish Kumar2ad402b2020-03-20 19:45:12 +00001061 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001062 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001063 }
1064
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001065 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001066
1067 // check the ONU is already know to the OLT
1068 // NOTE the second time the ONU is discovered this should return a device
1069 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1070
1071 if err != nil {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001072 logger.Debugw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001073 if e, ok := status.FromError(err); ok {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001074 logger.Debugw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001075 switch e.Code() {
1076 case codes.Internal:
1077 // this probably means NOT FOUND, so just create a new device
1078 onuDevice = nil
1079 case codes.DeadlineExceeded:
1080 // if the call times out, cleanup and exit
1081 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001082 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001083 }
1084 }
1085 }
1086
1087 if onuDevice == nil {
1088 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001089 logger.Debugw("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001090 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001091 ponintfid := onuDiscInd.GetIntfId()
1092 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301093 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001094 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001095
Girish Kumar2ad402b2020-03-20 19:45:12 +00001096 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001097
1098 if err != nil {
1099 // if we can't create an ID in resource manager,
1100 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001101 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001102 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001103 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001104 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001105 }
1106
1107 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1108 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001109 dh.discOnus.Delete(sn)
1110 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 +05301111 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001112 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001113 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001114 }
Amit Ghosh75f0e292020-05-14 11:31:54 +01001115 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Shrey Baid807a2a02020-04-09 12:52:45 +05301116 logger.Infow("onu-child-device-added",
1117 log.Fields{"onuDevice": onuDevice,
1118 "sn": sn,
1119 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301120 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001121 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001122
1123 // we can now use the existing ONU Id
1124 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001125 //Insert the ONU into cache to use in OnuIndication.
1126 //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 +05301127 logger.Debugw("onu-discovery-indication-key-create",
1128 log.Fields{"onuID": onuID,
1129 "intfId": onuDiscInd.GetIntfId(),
1130 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001131 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001132
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301133 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301134 dh.onus.Store(onuKey, onuDev)
Shrey Baid807a2a02020-04-09 12:52:45 +05301135 logger.Debugw("new-onu-device-discovered",
1136 log.Fields{"onu": onuDev,
1137 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001138
David K. Bainbridge794735f2020-02-11 21:01:37 -08001139 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301140 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001141 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001142 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001143 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301144 logger.Infow("onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001145 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301146 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001147 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001148 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149 }
1150 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001151}
1152
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001154 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1155
1156 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001157 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001158 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001160 foundInCache := false
Shrey Baid807a2a02020-04-09 12:52:45 +05301161 logger.Debugw("onu-indication-key-create",
1162 log.Fields{"onuId": onuInd.OnuId,
1163 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301164 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001165 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301166
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167 errFields := log.Fields{"device-id": dh.device.Id}
1168
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301169 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1170
Mahir Gunyele77977b2019-06-27 05:36:22 -07001171 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1172 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1174 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001175 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001176 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1177 if serialNumber != "" {
1178 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001179 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001180 } else {
1181 kwargs["onu_id"] = onuInd.OnuId
1182 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 errFields["onu-id"] = onuInd.OnuId
1184 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001185 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001187 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001188
David K. Bainbridge794735f2020-02-11 21:01:37 -08001189 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001190 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001191 }
1192
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 if onuDevice.ParentPortNo != ponPort {
Shrey Baid807a2a02020-04-09 12:52:45 +05301194 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001195 "previousIntfId": onuDevice.ParentPortNo,
1196 "currentIntfId": ponPort})
1197 }
1198
1199 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Shrey Baid807a2a02020-04-09 12:52:45 +05301200 logger.Warnw("onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
1201 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1202 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301203 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001204 }
1205 if !foundInCache {
1206 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1207
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301208 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 -08001209
1210 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001211 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001212 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001213 }
1214 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001215}
1216
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001217func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301218 ctx := context.TODO()
Shrey Baid807a2a02020-04-09 12:52:45 +05301219 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 +00001220 if onuInd.AdminState == "down" {
Girish Gowdra429f9502020-05-04 13:22:16 -07001221 // The ONU has gone admin_state "down" and we expect the ONU to send discovery again
1222 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001223 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1224 if onuInd.OperState != "down" {
Shrey Baid807a2a02020-04-09 12:52:45 +05301225 logger.Warnw("onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001226 onuInd.OperState = "down"
1227 }
1228 }
1229
David K. Bainbridge794735f2020-02-11 21:01:37 -08001230 switch onuInd.OperState {
1231 case "down":
Shrey Baid807a2a02020-04-09 12:52:45 +05301232 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 -07001233 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301234 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001235 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1236 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301237 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001238 "onu-indicator": onuInd,
1239 "source": "openolt",
1240 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001241 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001242 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001243 case "up":
Shrey Baid807a2a02020-04-09 12:52:45 +05301244 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 -04001245 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301246 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001247 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1248 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301249 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 "onu-indicator": onuInd,
1251 "source": "openolt",
1252 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001253 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001254 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001255 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001256 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001257 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001259}
1260
cuilin20187b2a8c32019-03-26 19:52:28 -07001261func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1262 if serialNum != nil {
1263 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001264 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001265 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001266}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001267func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1268 decodedStr, err := hex.DecodeString(serialNum[4:])
1269 if err != nil {
1270 return nil, err
1271 }
1272 return &oop.SerialNumber{
1273 VendorId: []byte(serialNum[:4]),
1274 VendorSpecific: []byte(decodedStr),
1275 }, nil
1276}
cuilin20187b2a8c32019-03-26 19:52:28 -07001277
1278func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1279 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001280 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001281 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1282 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1283 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1284 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1285 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1286 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1287 return tmp
1288}
1289
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001290//UpdateFlowsBulk upates the bulk flow
1291func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301292 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001293}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001294
1295//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001296func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301297 logger.Debugw("getchilddevice",
1298 log.Fields{"pon-port": parentPort,
1299 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301300 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001301 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001302 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001303 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001304 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001305 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001306 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001307 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001308 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001309 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301310 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 -08001311 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301312}
1313
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001314// SendPacketInToCore sends packet-in to core
1315// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1316// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001317func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001318 logger.Debugw("send-packet-in-to-core", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301319 "port": logicalPort,
1320 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301321 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001322 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001323 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301324 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001325 "source": "adapter",
1326 "destination": "core",
1327 "device-id": dh.device.Id,
1328 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001329 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001330 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301331 logger.Debugw("sent-packet-in-to-core-successfully", log.Fields{
1332 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301333 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001334 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001335 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001336}
1337
A R Karthick1f85b802019-10-11 05:06:05 +00001338// AddUniPortToOnu adds the uni port to the onu device
1339func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1340 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301341
1342 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001343 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301344 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1345 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001346 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001347 }
1348 }
1349}
1350
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001351//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301352func (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 +05301353 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 +01001354
1355 var errorsList []error
1356
Girish Gowdru0c588b22019-04-23 23:24:56 -04001357 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001358 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001359 dh.incrementActiveFlowRemoveCount(flow)
1360
Shrey Baid807a2a02020-04-09 12:52:45 +05301361 logger.Debugw("removing-flow",
1362 log.Fields{"device-id": device.Id,
1363 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001364 err := dh.flowMgr.RemoveFlow(ctx, flow)
1365 if err != nil {
1366 errorsList = append(errorsList, err)
1367 }
1368
1369 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001370 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301371
1372 for _, flow := range flows.ToAdd.Items {
Shrey Baid807a2a02020-04-09 12:52:45 +05301373 logger.Debugw("adding-flow",
1374 log.Fields{"device-id": device.Id,
1375 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001376 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1377 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001378 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1379 if err != nil {
1380 errorsList = append(errorsList, err)
1381 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301382 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001383 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001384
Girish Gowdracefae192020-03-19 18:14:10 -07001385 // 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 +00001386 if groups != nil {
1387 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001388 err := dh.flowMgr.AddGroup(ctx, group)
1389 if err != nil {
1390 errorsList = append(errorsList, err)
1391 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001392 }
1393 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001394 err := dh.flowMgr.ModifyGroup(ctx, group)
1395 if err != nil {
1396 errorsList = append(errorsList, err)
1397 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001398 }
1399 if len(groups.ToRemove.Items) != 0 {
Thomas Lee S985938d2020-05-04 11:40:41 +05301400 logger.Debugw("group-delete-operation-not-supported", log.Fields{"device-id": dh.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001401 }
1402 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001403 if len(errorsList) > 0 {
1404 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1405 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301406 logger.Debugw("updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001407 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301408}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001409
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001410//DisableDevice disables the given device
1411//It marks the following for the given device:
1412//Device-Handler Admin-State : down
1413//Device Port-State: UNKNOWN
1414//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001415func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001416 /* On device disable ,admin state update has to be done prior sending request to agent since
1417 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001418 if dh.Client != nil {
1419 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1420 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001421 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001422 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001423 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001424 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301425 logger.Debugw("olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001426 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001427 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301428
1429 dh.discOnus = sync.Map{}
1430 dh.onus = sync.Map{}
1431
Thomas Lee S85f37312020-04-03 17:06:12 +05301432 //stopping the stats collector
1433 dh.stopCollector <- true
1434
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301435 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001436 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301437 //Update device Admin state
1438 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001439 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1440 for _, port := range cloned.Ports {
1441 if port.GetType() == voltha.Port_PON_OLT {
1442 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1443 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001444 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001445 }
1446 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001447 }
1448
Shrey Baid807a2a02020-04-09 12:52:45 +05301449 logger.Debugw("disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001450 return nil
1451}
1452
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301453func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001454
1455 // Update onu state as unreachable in onu adapter
1456 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301457 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001458 //get the child device for the parent device
1459 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1460 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301461 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 -04001462 }
1463 if onuDevices != nil {
1464 for _, onuDevice := range onuDevices.Items {
1465 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1466 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1467 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001468 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301469 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001470 }
1471
1472 }
1473 }
1474
1475}
1476
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001477//ReenableDevice re-enables the olt device after disable
1478//It marks the following for the given device:
1479//Device-Handler Admin-State : up
1480//Device Port-State: ACTIVE
1481//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001482func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301483
1484 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1485 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001486 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301487 }
1488 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001489 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001490
1491 cloned := proto.Clone(device).(*voltha.Device)
1492 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001493
kdarapu1afeceb2020-02-12 01:38:09 -05001494 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001495 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001496 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001497 //Update the device oper status as ACTIVE
1498 cloned.OperStatus = voltha.OperStatus_ACTIVE
1499 dh.device = cloned
1500
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001501 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301502 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001503 "device-id": device.Id,
1504 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001505 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001506 }
kesavand39e0aa32020-01-28 20:58:50 -05001507
Shrey Baid807a2a02020-04-09 12:52:45 +05301508 logger.Debugw("reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001509
1510 return nil
1511}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001512
npujarec5762e2020-01-01 14:08:48 +05301513func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001514 var uniID uint32
1515 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301516 for _, port := range onu.UniPorts {
1517 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001518 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001519 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301520 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301521 logger.Debugw("failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001522 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301523 logger.Debugw("deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301524 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001525 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301526 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001527 }
npujarec5762e2020-01-01 14:08:48 +05301528 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001529 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301530 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301531 logger.Debugw("failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001532 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301533 logger.Debugw("removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301534 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301535 logger.Debugw("failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001536 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301537 logger.Debugw("removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301538 }
npujarec5762e2020-01-01 14:08:48 +05301539 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1540 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301541 logger.Debugw("failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301542 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301543 logger.Debugw("removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301544 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301545 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 +00001546 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001547 }
1548 return nil
1549}
1550
npujarec5762e2020-01-01 14:08:48 +05301551func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001552 nniUniID := -1
1553 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301554
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001555 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301556 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001557 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001558 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301559 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301560 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001561 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001562 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301563 logger.Debugw("nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301564 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301565 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Shrey Baid807a2a02020-04-09 12:52:45 +05301566 logger.Debugw("current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301567 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301568 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301569 }
npujarec5762e2020-01-01 14:08:48 +05301570 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001571 }
npujarec5762e2020-01-01 14:08:48 +05301572 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001573 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301574 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001575 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001576}
1577
1578// 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 +05301579func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301580 logger.Debug("function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001581 /* Clear the KV store data associated with the all the UNI ports
1582 This clears up flow data and also resource map data for various
1583 other pon resources like alloc_id and gemport_id
1584 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001585 go dh.cleanupDeviceResources(ctx)
Shrey Baid807a2a02020-04-09 12:52:45 +05301586 logger.Debug("removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001587 // Stop the Stats collector
1588 dh.stopCollector <- true
1589 // stop the heartbeat check routine
1590 dh.stopHeartbeatCheck <- true
1591 //Reset the state
1592 if dh.Client != nil {
1593 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301594 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001595 }
1596 }
1597 cloned := proto.Clone(device).(*voltha.Device)
1598 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1599 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1600 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1601 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1602 "device-id": device.Id,
1603 "connect-status": cloned.ConnectStatus,
1604 "oper-status": cloned.OperStatus}, err).Log()
1605 }
1606 return nil
1607}
1608func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001609 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301610 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1611 var ponPort uint32
1612 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1613 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301614 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301615 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301616 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001617 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001618 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301619 }
1620 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301621 onuID := make([]uint32, 1)
Shrey Baid807a2a02020-04-09 12:52:45 +05301622 logger.Debugw("onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301623 if err = dh.clearUNIData(ctx, &onu); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301624 logger.Errorw("failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301625 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301626 // Clear flowids for gem cache.
1627 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301628 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301629 }
1630 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301631 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301632 }
npujarec5762e2020-01-01 14:08:48 +05301633 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301634 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301635 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301636 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301637 logger.Errorw("failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001638 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001639 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001640 /* Clear the flows from KV store associated with NNI port.
1641 There are mostly trap rules from NNI port (like LLDP)
1642 */
npujarec5762e2020-01-01 14:08:48 +05301643 if err := dh.clearNNIData(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301644 logger.Errorw("failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001645 }
A R Karthick1f85b802019-10-11 05:06:05 +00001646
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001647 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301648 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001649 }
A R Karthick1f85b802019-10-11 05:06:05 +00001650
Devmalya Paul495b94a2019-08-27 19:42:00 -04001651 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301652 dh.onus.Range(func(key interface{}, value interface{}) bool {
1653 dh.onus.Delete(key)
1654 return true
1655 })
1656
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001657 /*Delete discovered ONU map for the device*/
1658 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1659 dh.discOnus.Delete(key)
1660 return true
1661 })
1662
Devmalya Paul495b94a2019-08-27 19:42:00 -04001663 return nil
1664}
1665
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001666//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001667func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1668 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301669 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001670 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301671 logger.Debugw("rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001672 return nil
1673}
1674
David K. Bainbridge794735f2020-02-11 21:01:37 -08001675func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301676 logger.Debugw("received-packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001677 "packet-indication": *packetIn,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001678 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001679 "packet": hex.EncodeToString(packetIn.Pkt),
1680 })
npujarec5762e2020-01-01 14:08:48 +05301681 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001682 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001683 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001684 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301685 logger.Debugw("sending-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001686 "logicalPortNum": logicalPortNum,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001687 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001688 "packet": hex.EncodeToString(packetIn.Pkt),
1689 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001690 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301691 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001692 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301693 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001694 "device-id": dh.device.Id,
1695 "packet": hex.EncodeToString(packetIn.Pkt),
1696 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001697 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301698 logger.Debugw("success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001699 "packet": hex.EncodeToString(packetIn.Pkt),
Thomas Lee S985938d2020-05-04 11:40:41 +05301700 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001701 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001702 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001703}
1704
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001705// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301706func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001707 logger.Debugw("incoming-packet-out", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301708 "device-id": dh.device.Id,
Shrey Baid807a2a02020-04-09 12:52:45 +05301709 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001710 "pkt-length": len(packet.Data),
1711 "packet": hex.EncodeToString(packet.Data),
1712 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001713
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001714 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001715 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001716 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1717 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301718 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1719 // Do not packet-out lldp packets on uni port.
1720 // ONOS has no clue about uni/nni ports, it just packets out on all
1721 // available ports on the Logical Switch. It should not be interested
1722 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001723 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1724 "device-id": dh.device.Id,
1725 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301726 return nil
1727 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001728 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1729 if innerEthType == 0x8100 {
1730 // q-in-q 802.1ad or 802.1q double tagged packet.
1731 // slice out the outer tag.
1732 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001733 logger.Debugw("packet-now-single-tagged", log.Fields{
1734 "packetData": hex.EncodeToString(packet.Data),
1735 "device-id": dh.device.Id,
1736 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001737 }
1738 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001739 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1740 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001741 uniID := UniIDFromPortNum(uint32(egressPortNo))
1742
npujarec5762e2020-01-01 14:08:48 +05301743 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001744 if err != nil {
1745 // In this case the openolt agent will receive the gemPortID as 0.
1746 // The agent tries to retrieve the gemPortID in this case.
1747 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001748 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001749 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301750 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001751 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001752 }
1753
1754 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001755
Girish Kumar2ad402b2020-03-20 19:45:12 +00001756 logger.Debugw("sending-packet-to-onu", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301757 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001758 "IntfId": intfID,
1759 "onuID": onuID,
1760 "uniID": uniID,
1761 "gemPortID": gemPortID,
1762 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301763 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001764 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001765
npujarec5762e2020-01-01 14:08:48 +05301766 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301767 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001768 "source": "adapter",
1769 "destination": "onu",
1770 "egress-port-number": egressPortNo,
1771 "interface-id": intfID,
1772 "oni-id": onuID,
1773 "uni-id": uniID,
1774 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001775 "packet": hex.EncodeToString(packet.Data),
1776 "device-id": dh.device.Id,
1777 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001778 }
1779 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001780 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1781 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001782 return olterrors.NewErrInvalidValue(log.Fields{
1783 "egress-nni-port": egressPortNo,
1784 "device-id": dh.device.Id,
1785 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001786 }
1787 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001788
Girish Kumar2ad402b2020-03-20 19:45:12 +00001789 logger.Debugw("sending-packet-to-nni", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301790 "uplink-pkt": uplinkPkt,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001791 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301792 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001793 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001794
npujarec5762e2020-01-01 14:08:48 +05301795 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001796 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1797 "packet": hex.EncodeToString(packet.Data),
1798 "device-id": dh.device.Id,
1799 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001800 }
1801 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301802 logger.Warnw("packet-out-to-this-interface-type-not-implemented", log.Fields{
1803 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001804 "egressPortType": egressPortType,
1805 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301806 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001807 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001808 }
1809 return nil
1810}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001811
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001812func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1813 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001814}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301815
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001816func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301817 // start the heartbeat check towards the OLT.
1818 var timerCheck *time.Timer
1819
1820 for {
1821 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1822 select {
1823 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001824 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1825 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301826 logger.Warnw("hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301827 if timerCheck == nil {
1828 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001829 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301830 }
1831 } else {
1832 if timerCheck != nil {
1833 if timerCheck.Stop() {
Thomas Lee S985938d2020-05-04 11:40:41 +05301834 logger.Debugw("got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301835 }
1836 timerCheck = nil
1837 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301838 logger.Debugw("hearbeat",
1839 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301840 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301841 }
1842 cancel()
1843 case <-dh.stopHeartbeatCheck:
Thomas Lee S985938d2020-05-04 11:40:41 +05301844 logger.Debugw("stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301845 return
1846 }
1847 }
1848}
1849
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001850func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1851 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1852 if err != nil || device == nil {
1853 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1854 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301855
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001856 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1857 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1858 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1859 }
1860 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1861 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1862 }
1863 go dh.cleanupDeviceResources(ctx)
1864
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001865 dh.lockDevice.RLock()
1866 // Stop the read indication only if it the routine is active
1867 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1868 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1869 // on next execution of the readIndication routine.
1870 if dh.isReadIndicationRoutineActive {
1871 dh.stopIndications <- true
1872 }
1873 dh.lockDevice.RUnlock()
1874
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001875 dh.transitionMap.Handle(ctx, DeviceInit)
1876
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301877 }
1878}
kesavand39e0aa32020-01-28 20:58:50 -05001879
1880// EnablePort to enable Pon interface
1881func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001882 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001883 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001884}
1885
1886// DisablePort to disable pon interface
1887func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001888 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001889 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001890}
1891
kdarapu1afeceb2020-02-12 01:38:09 -05001892//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1893func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301894 ctx := context.Background()
Thomas Lee S985938d2020-05-04 11:40:41 +05301895 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05001896 if port.GetType() == voltha.Port_ETHERNET_NNI {
1897 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001898 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301899 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301900 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001901 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001902 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001903 }
1904 // fetch interfaceid from PortNo
1905 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1906 ponIntf := &oop.Interface{IntfId: ponID}
1907 var operStatus voltha.OperStatus_Types
1908 if enablePort {
1909 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301910 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001911
1912 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301913 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001914 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001915 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001916 }
1917 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001918 dh.activePorts.Store(ponID, true)
Shrey Baid807a2a02020-04-09 12:52:45 +05301919 logger.Infow("enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001920 } else {
1921 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301922 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001923 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301924 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001925 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001926 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001927 }
1928 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001929 dh.activePorts.Store(ponID, false)
Shrey Baid807a2a02020-04-09 12:52:45 +05301930 logger.Infow("disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001931 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301932 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 +05301933 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301934 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001935 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001936 }
1937 return nil
1938}
1939
kdarapu1afeceb2020-02-12 01:38:09 -05001940//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1941func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001942 cloned := proto.Clone(device).(*voltha.Device)
1943 // Disable the port and update the oper_port_status to core
1944 // if the Admin state of the port is disabled on reboot and re-enable device.
1945 for _, port := range cloned.Ports {
1946 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001947 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301948 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301949 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001950 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001951 }
1952 }
1953 }
1954 return nil
1955}
1956
1957//populateActivePorts to populate activePorts map
1958func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301959 logger.Infow("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001960 for _, port := range device.Ports {
1961 if port.Type == voltha.Port_ETHERNET_NNI {
1962 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001963 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001964 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001965 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001966 }
1967 }
1968 if port.Type == voltha.Port_PON_OLT {
1969 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001970 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001971 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001972 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001973 }
1974 }
1975 }
1976}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001977
1978// ChildDeviceLost deletes ONU and clears pon resources related to it.
1979func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001980 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001981 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1982 onuKey := dh.formOnuKey(IntfID, onuID)
1983 onuDevice, ok := dh.onus.Load(onuKey)
1984 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301985 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001986 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301987 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001988 "onu-id": onuID,
1989 "interface-id": IntfID}, nil).Log()
1990 }
1991 var sn *oop.SerialNumber
1992 var err error
1993 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301994 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001995 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301996 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001997 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1998 }
1999 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
2000 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302001 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302002 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002003 "onu-id": onuID}, err).Log()
2004 }
2005 //clear PON resources associated with ONU
2006 var onuGemData []rsrcMgr.OnuGemInfo
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002007 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[IntfID]; !ok {
2008 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302009 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002010 "interface-id": IntfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002011 } else {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002012 if err := onuMgr.GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05302013 logger.Warnw("failed-to-get-onu-info-for-pon-port", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302014 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002015 "interface-id": IntfID,
2016 "error": err})
2017 } else {
2018 for i, onu := range onuGemData {
2019 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Shrey Baid807a2a02020-04-09 12:52:45 +05302020 logger.Debugw("onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002021 if err := dh.clearUNIData(ctx, &onu); err != nil {
2022 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302023 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002024 "onu-device": onu,
2025 "error": err})
2026 }
2027 // Clear flowids for gem cache.
2028 for _, gem := range onu.GemPorts {
2029 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
2030 }
2031 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
2032 err := onuMgr.AddOnuGemInfo(ctx, IntfID, onuGemData)
2033 if err != nil {
2034 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
2035 "interface-id": IntfID,
2036 "onu-device": onu,
2037 "onu-gem": onuGemData,
2038 "error": err})
2039 //Not returning error on cleanup.
2040 }
2041 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": IntfID, "onu-device": onu, "onugem": onuGemData})
2042 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
2043 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002044 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002045 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002046 }
2047 }
2048 dh.onus.Delete(onuKey)
2049 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2050 return nil
2051}
Girish Gowdracefae192020-03-19 18:14:10 -07002052
2053func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2054 for _, field := range flows.GetOfbFields(flow) {
2055 if field.Type == flows.IN_PORT {
2056 return field.GetPort()
2057 }
2058 }
2059 return InvalidPort
2060}
2061
2062func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2063 for _, action := range flows.GetActions(flow) {
2064 if action.Type == flows.OUTPUT {
2065 if out := action.GetOutput(); out != nil {
2066 return out.GetPort()
2067 }
2068 }
2069 }
2070 return InvalidPort
2071}
2072
2073func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2074 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302075 logger.Debugw("increment-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002076 if inPort != InvalidPort && outPort != InvalidPort {
2077 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2078 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302079 logger.Debugw("increment-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002080
2081 dh.lockDevice.Lock()
2082 defer dh.lockDevice.Unlock()
2083 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2084 if !ok {
2085 flowRemoveData = pendingFlowRemoveData{
2086 pendingFlowRemoveCount: 0,
2087 allFlowsRemoved: make(chan struct{}),
2088 }
2089 }
2090 flowRemoveData.pendingFlowRemoveCount++
2091 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2092
Shrey Baid807a2a02020-04-09 12:52:45 +05302093 logger.Debugw("current-flow-remove-count–increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002094 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2095 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2096 }
2097}
2098
2099func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2100 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302101 logger.Debugw("decrement-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002102 if inPort != InvalidPort && outPort != InvalidPort {
2103 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2104 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302105 logger.Debugw("decrement-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002106
2107 dh.lockDevice.Lock()
2108 defer dh.lockDevice.Unlock()
2109 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302110 logger.Fatalf("flow-remove-key-not-found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002111 } else {
2112 if val.pendingFlowRemoveCount > 0 {
2113 val.pendingFlowRemoveCount--
2114 }
Shrey Baid807a2a02020-04-09 12:52:45 +05302115 logger.Debugw("current-flow-remove-count-after-decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002116 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2117 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2118 // If all flow removes have finished, then close the channel to signal the receiver
2119 // to go ahead with flow adds.
2120 if val.pendingFlowRemoveCount == 0 {
2121 close(val.allFlowsRemoved)
2122 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2123 return
2124 }
2125 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2126 }
2127 }
2128}
2129
2130func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2131 var flowRemoveData pendingFlowRemoveData
2132 var ok bool
2133 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302134 logger.Debugw("wait-for-flow-remove-to-finish-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002135 if inPort != InvalidPort && outPort != InvalidPort {
2136 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2137 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302138 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 -07002139
2140 dh.lockDevice.RLock()
2141 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302142 logger.Debugw("no-pending-flow-to-remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002143 dh.lockDevice.RUnlock()
2144 return
2145 }
2146 dh.lockDevice.RUnlock()
2147
2148 // Wait for all flow removes to finish first
2149 <-flowRemoveData.allFlowsRemoved
2150
Shrey Baid807a2a02020-04-09 12:52:45 +05302151 logger.Debugw("all-flows-cleared--handling-flow-add-now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002152 }
2153}
2154
2155func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2156 inPort := getInPortFromFlow(flow)
2157 outPort := getOutPortFromFlow(flow)
2158
2159 if inPort == InvalidPort || outPort == InvalidPort {
2160 return inPort, outPort
2161 }
2162
2163 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2164 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2165 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2166 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2167 return uniPort, outPort
2168 }
2169 }
2170 } else {
2171 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2172 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2173 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2174 return inPort, uniPort
2175 }
2176 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2177 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2178 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2179 return uniPort, outPort
2180 }
2181 }
2182 }
2183
2184 return InvalidPort, InvalidPort
2185}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002186
2187func extractOmciTransactionID(omciPkt []byte) uint16 {
2188 if len(omciPkt) > 3 {
2189 d := omciPkt[0:2]
2190 transid := binary.BigEndian.Uint16(d)
2191 return transid
2192 }
2193 return 0
2194}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002195
2196// StoreOnuDevice stores the onu parameters to the local cache.
2197func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2198 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2199 dh.onus.Store(onuKey, onuDevice)
2200}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002201
2202func (dh *DeviceHandler) getExtValue(device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
2203 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002204 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002205 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002206 resp := new(voltha.ReturnValues)
2207 valueparam := new(oop.ValueParam)
2208 ctx := context.Background()
2209 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002210 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2211 return nil, err
2212 }
2213 ID = device.ProxyAddress.GetOnuId()
2214 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2215 valueparam.Onu = &Onu
2216 valueparam.Value = value
2217
2218 // This API is unsupported until agent patch is added
2219 resp.Unsupported = uint32(value)
2220 _ = ctx
2221
2222 // Uncomment this code once agent changes are complete and tests
2223 /*
2224 resp, err = dh.Client.GetValue(ctx, valueparam)
2225 if err != nil {
2226 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2227 return nil, err
2228 }
2229 */
2230
2231 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2232 return resp, nil
2233}