blob: 2cda87242f278805efb7b07771da05c45ce11708 [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
Matteo Scandolo945e4012019-12-12 14:16:11 -080034 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070035 "github.com/gogo/protobuf/proto"
36 "github.com/golang/protobuf/ptypes"
Esin Karamanccb714b2019-11-29 15:02:06 +000037 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
38 "github.com/opencord/voltha-lib-go/v3/pkg/log"
39 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Thomas Lee S94109f12020-03-03 16:39:29 +053040 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080041 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000042 "github.com/opencord/voltha-protos/v3/go/common"
43 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
44 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
45 oop "github.com/opencord/voltha-protos/v3/go/openolt"
46 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070047 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040048 "google.golang.org/grpc/codes"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040049 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053050)
51
salmansiddiqui7ac62132019-08-22 03:58:50 +000052// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040053const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000054 MaxRetry = 10
55 MaxTimeOutInMs = 500
Girish Gowdracefae192020-03-19 18:14:10 -070056 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040057)
58
Girish Gowdracefae192020-03-19 18:14:10 -070059// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
60type pendingFlowRemoveDataKey struct {
61 intfID uint32
62 onuID uint32
63 uniID uint32
64}
65
66// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
67// This holds the number of pending flow removes and also a signal channel to
68// to indicate the receiver when all flow removes are handled
69type pendingFlowRemoveData struct {
70 pendingFlowRemoveCount uint32
71 allFlowsRemoved chan struct{}
72}
73
Phaneendra Manda4c62c802019-03-06 21:37:49 +053074//DeviceHandler will interact with the OLT device.
75type DeviceHandler struct {
cuilin20187b2a8c32019-03-26 19:52:28 -070076 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053077 coreProxy adapterif.CoreProxy
78 AdapterProxy adapterif.AdapterProxy
79 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070080 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070081 exitChannel chan int
82 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053083 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070084 transitionMap *TransitionMap
85 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053086 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040087 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053088 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053089
Girish Gowdra3ab6d212020-03-24 17:33:15 -070090 discOnus sync.Map
91 onus sync.Map
92 portStats *OpenOltStatisticsMgr
93 metrics *pmmetrics.PmMetrics
94 stopCollector chan bool
95 stopHeartbeatCheck chan bool
96 activePorts sync.Map
97 stopIndications chan bool
98 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -070099
100 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
101 // subscriber basis for the number of pending flow removes. This data is used
102 // to process all the flow removes for a subscriber before handling flow adds.
103 // Interleaving flow delete and flow add processing has known to cause PON resource
104 // management contentions on a per subscriber bases, so we need ensure ordering.
105 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700106}
107
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700111 deviceType string
112 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 onuID uint32
114 intfID uint32
115 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +0000116 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530117 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400118 rdiRaised 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 Gowdra631ef3d2020-06-15 10:45:52 -0700292 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400293 // Now create Port
294 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700295 PortNo: portNum,
296 Label: label,
297 Type: portType,
298 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700299 OfpPort: &of.OfpPort{
300 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
301 Config: 0,
302 State: uint32(of.OfpPortState_OFPPS_LIVE),
303 Curr: capacity,
304 Advertised: capacity,
305 Peer: capacity,
306 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
307 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
308 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700309 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530310 logger.Debugw("sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700311 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700312 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000313 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800314 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000315 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400316 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530317 go dh.updateLocalDevice()
318 return nil
319}
320
321func (dh *DeviceHandler) updateLocalDevice() error {
322 dh.lockDevice.Lock()
323 defer dh.lockDevice.Unlock()
324 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
325 if err != nil || device == nil {
326 logger.Errorf("device", log.Fields{"device-id": dh.device.Id}, err)
327 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
328 }
329 dh.device = device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800330 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530331}
332
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700333// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530334// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800335func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000336 defer logger.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700337 defer func() {
338 dh.lockDevice.Lock()
339 dh.isReadIndicationRoutineActive = false
340 dh.lockDevice.Unlock()
341 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700342 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700343 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700344 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700345 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400346 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530347 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400348 if err != nil || device == nil {
349 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000350 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400351 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400352
David Bainbridgef5879ca2019-12-13 21:17:54 +0000353 // Create an exponential backoff around re-enabling indications. The
354 // maximum elapsed time for the back off is set to 0 so that we will
355 // continue to retry. The max interval defaults to 1m, but is set
356 // here for code clarity
357 indicationBackoff := backoff.NewExponentialBackOff()
358 indicationBackoff.MaxElapsedTime = 0
359 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700360
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700361 dh.lockDevice.Lock()
362 dh.isReadIndicationRoutineActive = true
363 dh.lockDevice.Unlock()
364
Girish Gowdra3f974912020-03-23 20:35:18 -0700365Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700366 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400367 select {
368 case <-dh.stopIndications:
Thomas Lee S985938d2020-05-04 11:40:41 +0530369 logger.Debugw("stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700370 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400371 default:
372 indication, err := indications.Recv()
373 if err == io.EOF {
Shrey Baid807a2a02020-04-09 12:52:45 +0530374 logger.Infow("eof-for-indications",
375 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530376 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400377 // Use an exponential back off to prevent getting into a tight loop
378 duration := indicationBackoff.NextBackOff()
379 if duration == backoff.Stop {
380 // If we reach a maximum then warn and reset the backoff
381 // timer and keep attempting.
Shrey Baid807a2a02020-04-09 12:52:45 +0530382 logger.Warnw("maximum-indication-backoff-reached--resetting-backoff-timer",
383 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530384 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400385 indicationBackoff.Reset()
386 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700387
388 // On failure process a backoff timer while watching for stopIndications
389 // events
390 backoff := time.NewTimer(indicationBackoff.NextBackOff())
391 select {
392 case <-dh.stopIndications:
393 logger.Debugw("stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
394 if !backoff.Stop() {
395 <-backoff.C
396 }
397 break Loop
398 case <-backoff.C:
399 // backoff expired continue
400 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700401 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
402 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400403 }
404 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000405 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530406 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530407 logger.Errorw("read-indication-error",
408 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530409 "device-id": dh.device.Id})
410 if device.AdminState == voltha.AdminState_DELETED {
Shrey Baid807a2a02020-04-09 12:52:45 +0530411 logger.Debug("device-deleted--stopping-the-read-indication-thread")
Girish Gowdra3f974912020-03-23 20:35:18 -0700412 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400413 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700414 // Close the stream, and re-initialize it
415 if err = indications.CloseSend(); err != nil {
416 // Ok to ignore here, because we landed here due to a problem on the stream
417 // In all probability, the closeSend call may fail
Shrey Baid807a2a02020-04-09 12:52:45 +0530418 logger.Debugw("error-closing-send stream--error-ignored",
419 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530420 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700421 }
422 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
423 return err
424 }
425 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400426 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530427 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400428 // Reset backoff if we have a successful receive
429 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400430 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530431 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530432 logger.Debugw("olt-is-admin-down, ignore indication",
433 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530434 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400435 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400436 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400437 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700438 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700439 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700440 // Close the send stream
441 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700442
Girish Gowdra3f974912020-03-23 20:35:18 -0700443 return nil
444}
445
446func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
447
448 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
449 if err != nil {
450 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
451 }
452 if indications == nil {
453 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
454 }
455
456 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400457}
458
459// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
460func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
461 switch indication.Data.(type) {
462 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
463 return true
464
465 default:
466 return false
467 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700468}
469
David K. Bainbridge794735f2020-02-11 21:01:37 -0800470func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000471 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000472 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530473 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700474 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530475 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700476 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000477 // Send or clear Alarm
Thomas Lee S985938d2020-05-04 11:40:41 +0530478 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530479 return olterrors.NewErrAdapter("failed-indication", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530480 "device_id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000482 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800483 }
484 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700485}
486
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530488func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400489 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 switch indication.Data.(type) {
491 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800492 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530493 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800494 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700495 case *oop.Indication_IntfInd:
496 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800497 go func() {
498 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530499 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800500 }
501 }()
Thomas Lee S985938d2020-05-04 11:40:41 +0530502 logger.Infow("received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700503 case *oop.Indication_IntfOperInd:
504 intfOperInd := indication.GetIntfOperInd()
505 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800506 go func() {
507 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530508 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 -0800509 }
510 }()
npujarec5762e2020-01-01 14:08:48 +0530511 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700512 } else if intfOperInd.GetType() == "pon" {
513 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
514 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800515 go func() {
516 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530517 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 -0800518 }
519 }()
Thomas Lee S985938d2020-05-04 11:40:41 +0530520 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700521 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530522 logger.Infow("received-interface-oper-indication",
523 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530524 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525 case *oop.Indication_OnuDiscInd:
526 onuDiscInd := indication.GetOnuDiscInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530527 logger.Infow("received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700528 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800529 go func() {
530 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530531 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 -0800532 }
533 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700534 case *oop.Indication_OnuInd:
535 onuInd := indication.GetOnuInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530536 logger.Infow("received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800537 go func() {
538 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530539 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800540 }
541 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700542 case *oop.Indication_OmciInd:
543 omciInd := indication.GetOmciInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530544 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 -0800545 go func() {
546 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530547 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800548 }
549 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700550 case *oop.Indication_PktInd:
551 pktInd := indication.GetPktInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530552 logger.Infow("received-packet-indication", log.Fields{"PktInd": pktInd, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800553 go func() {
554 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530555 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800556 }
557 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700558 case *oop.Indication_PortStats:
559 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530560 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700561 case *oop.Indication_FlowStats:
562 flowStats := indication.GetFlowStats()
Thomas Lee S985938d2020-05-04 11:40:41 +0530563 logger.Infow("received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700564 case *oop.Indication_AlarmInd:
565 alarmInd := indication.GetAlarmInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530566 logger.Infow("received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
567 go dh.eventMgr.ProcessEvents(alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700568 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530569}
570
571// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530572func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530573 //starting the stat collector
574 go startCollector(dh)
575
Girish Gowdru0c588b22019-04-23 23:24:56 -0400576 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530577 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400578 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000579 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400580 }
581 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530582}
583
584// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530585func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700586 dh.lockDevice.Lock()
587 defer dh.lockDevice.Unlock()
Thomas Lee S985938d2020-05-04 11:40:41 +0530588 logger.Debugw("do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400589
npujarec5762e2020-01-01 14:08:48 +0530590 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400591 if err != nil || device == nil {
592 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000593 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400594 }
595
596 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400597
598 //Update the device oper state and connection status
599 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400600 dh.device = cloned
601
David K. Bainbridge794735f2020-02-11 21:01:37 -0800602 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000603 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400604 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400605
606 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530607 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400608 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000609 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400610 }
611 for _, onuDevice := range onuDevices.Items {
612
613 // Update onu state as down in onu adapter
614 onuInd := oop.OnuIndication{}
615 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800616 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700617 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800618 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530619 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800620 "source": "openolt",
621 "onu-indicator": onuInd,
622 "device-type": onuDevice.Type,
623 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700624 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700625 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400626 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700627 /* Discovered ONUs entries need to be cleared , since after OLT
628 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530629 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000630 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700631 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530632}
633
634// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530635func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400636 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800637 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530638 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530639 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000640 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400641 }
642 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530643}
644
645// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530646func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400647 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530648 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400649 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530650}
651
652// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530653func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530654 var err error
655 logger.Debugw("olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400656
657 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530658 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
659 if err != nil || device == nil {
660 /*TODO: needs to handle error scenarios */
661 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
662 }
663 if device.AdminState == voltha.AdminState_DISABLED {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000664 logger.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400665
666 cloned := proto.Clone(device).(*voltha.Device)
667 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
668 cloned.OperStatus = voltha.OperStatus_UNKNOWN
669 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530670 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
671 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 -0400672 }
673
Chaitrashree G S44124192019-08-07 20:21:36 -0400674 // 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 +0530675 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400676 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530677 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400678 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400679 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
680 // all the modules initialized and ready to handle incoming ONUs.
681
Thomas Lee S985938d2020-05-04 11:40:41 +0530682 err = dh.initializeDeviceHandlerModules(ctx)
683 if err != nil {
684 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 -0400685 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400686
687 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800688 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530689 if err = dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530690 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800691 }
692 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400693 return nil
694 }
695
Thomas Lee S985938d2020-05-04 11:40:41 +0530696 device, err = dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400697 if err != nil || device == nil {
698 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000699 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400700 }
kesavand39e0aa32020-01-28 20:58:50 -0500701 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500702 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000703 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400704 }
705
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400706 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530707 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 -0400708 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530709
cuilin20187b2a8c32019-03-26 19:52:28 -0700710 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800711 go func() {
712 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530713 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800714 }
715 }()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530716 go dh.updateLocalDevice()
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000717
718 if device.PmConfigs != nil {
719 dh.UpdatePmConfig(device.PmConfigs)
720 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700721 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530722}
723
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400724func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
725 deviceInfo, err := dh.populateDeviceInfo()
726
727 if err != nil {
728 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
729 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400730 // Instantiate resource manager
Neha Sharma3f221ae2020-04-29 19:02:12 +0000731 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, deviceInfo); dh.resourceMgr == nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400732 return olterrors.ErrResourceManagerInstantiating
733 }
734
735 // Instantiate flow manager
736 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
737 return olterrors.ErrResourceManagerInstantiating
738
739 }
740 /* TODO: Instantiate Alarm , stats , BW managers */
741 /* Instantiating Event Manager to handle Alarms and KPIs */
742 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
743
744 // Stats config for new device
745 dh.portStats = NewOpenOltStatsMgr(dh)
746
747 return nil
748
749}
750
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400751func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
752 var err error
753 var deviceInfo *oop.DeviceInfo
754
755 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
756
757 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000758 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400759 }
760 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000761 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400762 }
763
Thomas Lee S985938d2020-05-04 11:40:41 +0530764 logger.Debugw("fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400765 dh.device.Root = true
766 dh.device.Vendor = deviceInfo.Vendor
767 dh.device.Model = deviceInfo.Model
768 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
769 dh.device.HardwareVersion = deviceInfo.HardwareVersion
770 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
771
772 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000773 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400774 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
775 genmac, err := generateMacFromHost(host)
776 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000777 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400778 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000779 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400780 dh.device.MacAddress = genmac
781 } else {
782 dh.device.MacAddress = deviceInfo.DeviceId
783 }
784
785 // Synchronous call to update device - this method is run in its own go routine
786 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000787 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400788 }
789
790 return deviceInfo, nil
791}
792
Naga Manjunath7615e552019-10-11 22:35:47 +0530793func startCollector(dh *DeviceHandler) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530794 logger.Debugf("starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530795 for {
796 select {
797 case <-dh.stopCollector:
Thomas Lee S985938d2020-05-04 11:40:41 +0530798 logger.Debugw("stopping-collector-for-olt", log.Fields{"deviceID:": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530799 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000800 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700801
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530802 ports := make([]*voltha.Port, len(dh.device.Ports))
803 copy(ports, dh.device.Ports)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530804 for _, port := range ports {
805 // NNI Stats
806 if port.Type == voltha.Port_ETHERNET_NNI {
807 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
808 cmnni := dh.portStats.collectNNIMetrics(intfID)
809 logger.Debugw("collect-nni-metrics", log.Fields{"metrics": cmnni})
Girish Gowdra34815db2020-05-11 17:18:04 -0700810 go dh.portStats.publishMetrics(cmnni, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530811 logger.Debugw("publish-nni-metrics", log.Fields{"nni-port": port.Label})
812 }
813 // PON Stats
814 if port.Type == voltha.Port_PON_OLT {
815 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
816 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
817 cmpon := dh.portStats.collectPONMetrics(intfID)
818 logger.Debugw("collect-pon-metrics", log.Fields{"metrics": cmpon})
Girish Gowdra34815db2020-05-11 17:18:04 -0700819 go dh.portStats.publishMetrics(cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530820 }
821 logger.Debugw("publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500822 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530823 }
824 }
825 }
826}
827
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700828//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530829func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400830 dh.transitionMap = NewTransitionMap(dh)
Shrey Baid807a2a02020-04-09 12:52:45 +0530831 logger.Infow("adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530832 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530833
834 // Now, set the initial PM configuration for that device
835 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530836 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530837 }
838
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400839 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530840}
841
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700842//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530843func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700844 return &ic.SwitchCapability{
845 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530846 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700847 HwDesc: "open_pon",
848 SwDesc: "open_pon",
849 SerialNum: dh.device.SerialNumber,
850 },
851 SwitchFeatures: &of.OfpSwitchFeatures{
852 NBuffers: 256,
853 NTables: 2,
854 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
855 of.OfpCapabilities_OFPC_TABLE_STATS |
856 of.OfpCapabilities_OFPC_PORT_STATS |
857 of.OfpCapabilities_OFPC_GROUP_STATS),
858 },
859 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530860}
861
David K. Bainbridge794735f2020-02-11 21:01:37 -0800862func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530863 logger.Debugw("omci-indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700864 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700865 var deviceID string
866 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700867
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400868 transid := extractOmciTransactionID(omciInd.Pkt)
Thomas Lee S985938d2020-05-04 11:40:41 +0530869 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 -0400870 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
871
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700872 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530873
874 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
875
Thomas Lee S985938d2020-05-04 11:40:41 +0530876 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 -0700877 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700878 kwargs := make(map[string]interface{})
879 kwargs["onu_id"] = omciInd.OnuId
880 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700881
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700882 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
883 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530884 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800885 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000886 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700887 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700888 deviceType = onuDevice.Type
889 deviceID = onuDevice.Id
890 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
891 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530892 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700893 } else {
894 //found in cache
Thomas Lee S985938d2020-05-04 11:40:41 +0530895 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 +0530896 deviceType = onuInCache.(*OnuDevice).deviceType
897 deviceID = onuInCache.(*OnuDevice).deviceID
898 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700899 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700900
901 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800902 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Thomas Lee S985938d2020-05-04 11:40:41 +0530903 ic.InterAdapterMessageType_OMCI_REQUEST, dh.device.Type, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800904 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530905 return olterrors.NewErrCommunication("omci-request", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530906 "source": dh.device.Type,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800907 "destination": deviceType,
908 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000909 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700910 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800911 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530912}
913
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700914//ProcessInterAdapterMessage sends the proxied messages to the target device
915// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
916// is meant, and then send the unmarshalled omci message to this onu
917func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530918 logger.Debugw("process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700919 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700920 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700921 fromTopic := msg.Header.FromTopic
922 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700923 toDeviceID := msg.Header.ToDeviceId
924 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700925
Shrey Baid807a2a02020-04-09 12:52:45 +0530926 logger.Debugw("omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700927
928 msgBody := msg.GetBody()
929
930 omciMsg := &ic.InterAdapterOmciMessage{}
931 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000932 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700933 }
934
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700935 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700936 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
937 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530938 return olterrors.NewErrNotFound("onu", 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)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700941 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530942 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 -0800943 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530944 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800945 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000946 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800947 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700948 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +0530949 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 -0800950 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530951 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800952 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000953 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800954 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700955 }
956
957 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000958 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700959 }
960 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530961}
962
David K. Bainbridge794735f2020-02-11 21:01:37 -0800963func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700964 var intfID uint32
965 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000966 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700967 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700968 intfID = onuDevice.ProxyAddress.GetChannelId()
969 onuID = onuDevice.ProxyAddress.GetOnuId()
970 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700971 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700972 intfID = omciMsg.GetProxyAddress().GetChannelId()
973 onuID = omciMsg.GetProxyAddress().GetOnuId()
974 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700975 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976 if connectStatus != voltha.ConnectStatus_REACHABLE {
Shrey Baid807a2a02020-04-09 12:52:45 +0530977 logger.Debugw("onu-not-reachable--cannot-send-omci", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800978
Thomas Lee S94109f12020-03-03 16:39:29 +0530979 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800980 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000981 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700982 }
983
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400984 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
985 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700986 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400987 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
988 hex.Encode(hexPkt, omciMsg.Message)
989 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
990
991 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
992 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
993 transid := extractOmciTransactionID(omciMsg.Message)
994 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
995 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700996
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700997 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
998 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530999 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001000 "interface-id": intfID,
1001 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001002 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001003 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001004 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001005}
1006
David K. Bainbridge794735f2020-02-11 21:01:37 -08001007func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Thomas Lee S985938d2020-05-04 11:40:41 +05301008 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 +02001009 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
1010 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
1011 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001012 // TODO: need resource manager
1013 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301015 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001016 st, _ := status.FromError(err)
1017 if st.Code() == codes.AlreadyExists {
Thomas Lee S985938d2020-05-04 11:40:41 +05301018 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 -04001019 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301020 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001021 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001022 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301023 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001024 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001025 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001026}
1027
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001029
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001030 channelID := onuDiscInd.GetIntfId()
1031 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001032
Girish Kumar2ad402b2020-03-20 19:45:12 +00001033 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301034
cuilin20187b2a8c32019-03-26 19:52:28 -07001035 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001036 if sn != "" {
1037 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001038 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001039 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001040 }
1041
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301042 var alarmInd oop.OnuAlarmIndication
1043 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001044 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301045
1046 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1047 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1048 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1049 OnuLosRaise event sent for it */
1050 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1051 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1052 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Shrey Baid807a2a02020-04-09 12:52:45 +05301053 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301054 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1055 "currentIntfId": onuDiscInd.GetIntfId()})
1056 // TODO:: Should we need to ignore raising OnuLosClear event
1057 // when onu connected to different PON?
1058 }
1059 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1060 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1061 alarmInd.LosStatus = statusCheckOff
1062 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1063 }
1064 return true
1065 })
1066
Girish Kumar2ad402b2020-03-20 19:45:12 +00001067 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001069 }
1070
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001071 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001072
1073 // check the ONU is already know to the OLT
1074 // NOTE the second time the ONU is discovered this should return a device
1075 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1076
1077 if err != nil {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001078 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 -08001079 if e, ok := status.FromError(err); ok {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001080 logger.Debugw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001081 switch e.Code() {
1082 case codes.Internal:
1083 // this probably means NOT FOUND, so just create a new device
1084 onuDevice = nil
1085 case codes.DeadlineExceeded:
1086 // if the call times out, cleanup and exit
1087 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001088 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001089 }
1090 }
1091 }
1092
1093 if onuDevice == nil {
1094 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001095 logger.Debugw("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001096 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001097 ponintfid := onuDiscInd.GetIntfId()
1098 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301099 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001100 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001101
Girish Kumar2ad402b2020-03-20 19:45:12 +00001102 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001103
1104 if err != nil {
1105 // if we can't create an ID in resource manager,
1106 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001107 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001108 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001109 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001110 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001111 }
1112
1113 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1114 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001115 dh.discOnus.Delete(sn)
1116 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 +05301117 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001118 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001119 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001120 }
Amit Ghosh75f0e292020-05-14 11:31:54 +01001121 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Shrey Baid807a2a02020-04-09 12:52:45 +05301122 logger.Infow("onu-child-device-added",
1123 log.Fields{"onuDevice": onuDevice,
1124 "sn": sn,
1125 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301126 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001127 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001128
1129 // we can now use the existing ONU Id
1130 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001131 //Insert the ONU into cache to use in OnuIndication.
1132 //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 +05301133 logger.Debugw("onu-discovery-indication-key-create",
1134 log.Fields{"onuID": onuID,
1135 "intfId": onuDiscInd.GetIntfId(),
1136 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001137 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001138
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301139 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301140 dh.onus.Store(onuKey, onuDev)
Shrey Baid807a2a02020-04-09 12:52:45 +05301141 logger.Debugw("new-onu-device-discovered",
1142 log.Fields{"onu": onuDev,
1143 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001144
David K. Bainbridge794735f2020-02-11 21:01:37 -08001145 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301146 return olterrors.NewErrAdapter("failed-to-update-device-state", 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)
cuilin20187b2a8c32019-03-26 19:52:28 -07001149 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301150 logger.Infow("onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001151 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301152 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001154 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001155 }
1156 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001157}
1158
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001160 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1161
1162 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001163 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001164 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001166 foundInCache := false
Shrey Baid807a2a02020-04-09 12:52:45 +05301167 logger.Debugw("onu-indication-key-create",
1168 log.Fields{"onuId": onuInd.OnuId,
1169 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301170 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001171 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301172
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 errFields := log.Fields{"device-id": dh.device.Id}
1174
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301175 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1176
Mahir Gunyele77977b2019-06-27 05:36:22 -07001177 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1178 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001179 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1180 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001181 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001182 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1183 if serialNumber != "" {
1184 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001185 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001186 } else {
1187 kwargs["onu_id"] = onuInd.OnuId
1188 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001189 errFields["onu-id"] = onuInd.OnuId
1190 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001191 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001193 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001194
David K. Bainbridge794735f2020-02-11 21:01:37 -08001195 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001196 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001197 }
1198
David K. Bainbridge794735f2020-02-11 21:01:37 -08001199 if onuDevice.ParentPortNo != ponPort {
Shrey Baid807a2a02020-04-09 12:52:45 +05301200 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001201 "previousIntfId": onuDevice.ParentPortNo,
1202 "currentIntfId": ponPort})
1203 }
1204
1205 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Shrey Baid807a2a02020-04-09 12:52:45 +05301206 logger.Warnw("onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
1207 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1208 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301209 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 }
1211 if !foundInCache {
1212 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1213
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301214 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 -08001215
1216 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001217 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001218 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001219 }
1220 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001221}
1222
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001223func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301224 ctx := context.TODO()
Shrey Baid807a2a02020-04-09 12:52:45 +05301225 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 +00001226 if onuInd.AdminState == "down" {
Girish Gowdra429f9502020-05-04 13:22:16 -07001227 // The ONU has gone admin_state "down" and we expect the ONU to send discovery again
1228 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001229 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1230 if onuInd.OperState != "down" {
Shrey Baid807a2a02020-04-09 12:52:45 +05301231 logger.Warnw("onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001232 onuInd.OperState = "down"
1233 }
1234 }
1235
David K. Bainbridge794735f2020-02-11 21:01:37 -08001236 switch onuInd.OperState {
1237 case "down":
Shrey Baid807a2a02020-04-09 12:52:45 +05301238 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 -07001239 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301240 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001241 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1242 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301243 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 "onu-indicator": onuInd,
1245 "source": "openolt",
1246 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001247 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001248 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001249 case "up":
Shrey Baid807a2a02020-04-09 12:52:45 +05301250 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 -04001251 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301252 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001253 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1254 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301255 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 "onu-indicator": onuInd,
1257 "source": "openolt",
1258 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001259 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001260 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001261 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001262 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001263 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001265}
1266
cuilin20187b2a8c32019-03-26 19:52:28 -07001267func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1268 if serialNum != nil {
1269 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001270 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001271 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001272}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001273func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1274 decodedStr, err := hex.DecodeString(serialNum[4:])
1275 if err != nil {
1276 return nil, err
1277 }
1278 return &oop.SerialNumber{
1279 VendorId: []byte(serialNum[:4]),
1280 VendorSpecific: []byte(decodedStr),
1281 }, nil
1282}
cuilin20187b2a8c32019-03-26 19:52:28 -07001283
1284func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1285 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001286 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001287 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1288 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1289 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1290 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1291 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1292 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1293 return tmp
1294}
1295
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001296//UpdateFlowsBulk upates the bulk flow
1297func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301298 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001299}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001300
1301//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001302func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301303 logger.Debugw("getchilddevice",
1304 log.Fields{"pon-port": parentPort,
1305 "onuID": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301306 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001307 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001308 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001309 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001310 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001311 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001312 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001313 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001314 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001315 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301316 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 -08001317 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301318}
1319
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001320// SendPacketInToCore sends packet-in to core
1321// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1322// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001323func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001324 logger.Debugw("send-packet-in-to-core", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301325 "port": logicalPort,
1326 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301327 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001328 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001329 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301330 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001331 "source": "adapter",
1332 "destination": "core",
1333 "device-id": dh.device.Id,
1334 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001335 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001336 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301337 logger.Debugw("sent-packet-in-to-core-successfully", log.Fields{
1338 "packet": hex.EncodeToString(packetPayload),
Thomas Lee S985938d2020-05-04 11:40:41 +05301339 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001340 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001341 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001342}
1343
A R Karthick1f85b802019-10-11 05:06:05 +00001344// AddUniPortToOnu adds the uni port to the onu device
1345func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1346 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301347
1348 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001349 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301350 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1351 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001352 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001353 }
1354 }
1355}
1356
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001357// UpdatePmConfig updates the pm metrics.
1358func (dh *DeviceHandler) UpdatePmConfig(pmConfigs *voltha.PmConfigs) {
1359
1360 logger.Infow("update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
1361
1362 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1363 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
1364 logger.Debugf("frequency-updated")
1365 }
1366
1367 if pmConfigs.Grouped == false {
1368 metrics := dh.metrics.GetSubscriberMetrics()
1369 for _, m := range pmConfigs.Metrics {
1370 metrics[m.Name].Enabled = m.Enabled
1371
1372 }
1373 }
1374}
1375
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001376//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301377func (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 +05301378 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 +01001379
1380 var errorsList []error
1381
Girish Gowdru0c588b22019-04-23 23:24:56 -04001382 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001383 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001384 dh.incrementActiveFlowRemoveCount(flow)
1385
Shrey Baid807a2a02020-04-09 12:52:45 +05301386 logger.Debugw("removing-flow",
1387 log.Fields{"device-id": device.Id,
1388 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001389 err := dh.flowMgr.RemoveFlow(ctx, flow)
1390 if err != nil {
1391 errorsList = append(errorsList, err)
1392 }
1393
1394 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001395 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301396
1397 for _, flow := range flows.ToAdd.Items {
Shrey Baid807a2a02020-04-09 12:52:45 +05301398 logger.Debugw("adding-flow",
1399 log.Fields{"device-id": device.Id,
1400 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001401 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1402 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001403 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1404 if err != nil {
1405 errorsList = append(errorsList, err)
1406 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301407 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001408 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001409
Girish Gowdracefae192020-03-19 18:14:10 -07001410 // 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 +00001411 if groups != nil {
1412 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001413 err := dh.flowMgr.AddGroup(ctx, group)
1414 if err != nil {
1415 errorsList = append(errorsList, err)
1416 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001417 }
1418 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001419 err := dh.flowMgr.ModifyGroup(ctx, group)
1420 if err != nil {
1421 errorsList = append(errorsList, err)
1422 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001423 }
1424 if len(groups.ToRemove.Items) != 0 {
Thomas Lee S985938d2020-05-04 11:40:41 +05301425 logger.Debugw("group-delete-operation-not-supported", log.Fields{"device-id": dh.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001426 }
1427 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001428 if len(errorsList) > 0 {
1429 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1430 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301431 logger.Debugw("updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001432 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301433}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001434
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001435//DisableDevice disables the given device
1436//It marks the following for the given device:
1437//Device-Handler Admin-State : down
1438//Device Port-State: UNKNOWN
1439//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001440func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001441 /* On device disable ,admin state update has to be done prior sending request to agent since
1442 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001443 if dh.Client != nil {
1444 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1445 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001446 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001447 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001448 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001449 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301450 logger.Debugw("olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001451 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001452 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301453
1454 dh.discOnus = sync.Map{}
1455 dh.onus = sync.Map{}
1456
Thomas Lee S85f37312020-04-03 17:06:12 +05301457 //stopping the stats collector
1458 dh.stopCollector <- true
1459
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301460 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001461 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301462 //Update device Admin state
1463 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001464 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1465 for _, port := range cloned.Ports {
1466 if port.GetType() == voltha.Port_PON_OLT {
1467 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1468 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001469 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001470 }
1471 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001472 }
1473
Shrey Baid807a2a02020-04-09 12:52:45 +05301474 logger.Debugw("disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001475 return nil
1476}
1477
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301478func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001479
1480 // Update onu state as unreachable in onu adapter
1481 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301482 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001483 //get the child device for the parent device
1484 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1485 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301486 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 -04001487 }
1488 if onuDevices != nil {
1489 for _, onuDevice := range onuDevices.Items {
1490 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1491 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1492 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001493 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301494 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001495 }
1496
1497 }
1498 }
1499
1500}
1501
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001502//ReenableDevice re-enables the olt device after disable
1503//It marks the following for the given device:
1504//Device-Handler Admin-State : up
1505//Device Port-State: ACTIVE
1506//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001507func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301508
1509 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1510 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001511 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301512 }
1513 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001514 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001515
1516 cloned := proto.Clone(device).(*voltha.Device)
1517 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001518
kdarapu1afeceb2020-02-12 01:38:09 -05001519 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001520 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001521 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001522 //Update the device oper status as ACTIVE
1523 cloned.OperStatus = voltha.OperStatus_ACTIVE
1524 dh.device = cloned
1525
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001526 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301527 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001528 "device-id": device.Id,
1529 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001530 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001531 }
kesavand39e0aa32020-01-28 20:58:50 -05001532
Shrey Baid807a2a02020-04-09 12:52:45 +05301533 logger.Debugw("reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001534
1535 return nil
1536}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001537
npujarec5762e2020-01-01 14:08:48 +05301538func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001539 var uniID uint32
1540 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301541 for _, port := range onu.UniPorts {
1542 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001543 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001544 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301545 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301546 logger.Debugw("failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001547 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301548 logger.Debugw("deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301549 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001550 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301551 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001552 }
npujarec5762e2020-01-01 14:08:48 +05301553 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001554 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301555 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301556 logger.Debugw("failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001557 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301558 logger.Debugw("removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301559 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301560 logger.Debugw("failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001561 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301562 logger.Debugw("removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301563 }
npujarec5762e2020-01-01 14:08:48 +05301564 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1565 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301566 logger.Debugw("failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301567 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301568 logger.Debugw("removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301569 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301570 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 +00001571 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001572 }
1573 return nil
1574}
1575
npujarec5762e2020-01-01 14:08:48 +05301576func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001577 nniUniID := -1
1578 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301579
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001580 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301581 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001582 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001583 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301584 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301585 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001586 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001587 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301588 logger.Debugw("nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301589 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301590 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Shrey Baid807a2a02020-04-09 12:52:45 +05301591 logger.Debugw("current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301592 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301593 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301594 }
npujarec5762e2020-01-01 14:08:48 +05301595 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001596 }
npujarec5762e2020-01-01 14:08:48 +05301597 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001598 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301599 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001601}
1602
1603// 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 +05301604func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301605 logger.Debug("function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001606 /* Clear the KV store data associated with the all the UNI ports
1607 This clears up flow data and also resource map data for various
1608 other pon resources like alloc_id and gemport_id
1609 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001610 go dh.cleanupDeviceResources(ctx)
Shrey Baid807a2a02020-04-09 12:52:45 +05301611 logger.Debug("removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001612 // Stop the Stats collector
1613 dh.stopCollector <- true
1614 // stop the heartbeat check routine
1615 dh.stopHeartbeatCheck <- true
1616 //Reset the state
1617 if dh.Client != nil {
1618 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301619 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001620 }
1621 }
1622 cloned := proto.Clone(device).(*voltha.Device)
1623 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1624 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1625 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1626 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1627 "device-id": device.Id,
1628 "connect-status": cloned.ConnectStatus,
1629 "oper-status": cloned.OperStatus}, err).Log()
1630 }
1631 return nil
1632}
1633func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001634 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301635 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1636 var ponPort uint32
1637 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1638 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301639 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301640 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301641 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001642 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001643 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301644 }
1645 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301646 onuID := make([]uint32, 1)
Shrey Baid807a2a02020-04-09 12:52:45 +05301647 logger.Debugw("onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301648 if err = dh.clearUNIData(ctx, &onu); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301649 logger.Errorw("failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301650 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301651 // Clear flowids for gem cache.
1652 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301653 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301654 }
1655 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301656 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301657 }
npujarec5762e2020-01-01 14:08:48 +05301658 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301659 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301660 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301661 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301662 logger.Errorw("failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001663 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001664 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001665 /* Clear the flows from KV store associated with NNI port.
1666 There are mostly trap rules from NNI port (like LLDP)
1667 */
npujarec5762e2020-01-01 14:08:48 +05301668 if err := dh.clearNNIData(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301669 logger.Errorw("failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001670 }
A R Karthick1f85b802019-10-11 05:06:05 +00001671
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001672 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301673 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001674 }
A R Karthick1f85b802019-10-11 05:06:05 +00001675
Devmalya Paul495b94a2019-08-27 19:42:00 -04001676 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301677 dh.onus.Range(func(key interface{}, value interface{}) bool {
1678 dh.onus.Delete(key)
1679 return true
1680 })
1681
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001682 /*Delete discovered ONU map for the device*/
1683 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1684 dh.discOnus.Delete(key)
1685 return true
1686 })
1687
Devmalya Paul495b94a2019-08-27 19:42:00 -04001688 return nil
1689}
1690
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001691//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001692func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1693 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301694 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001695 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301696 logger.Debugw("rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001697 return nil
1698}
1699
David K. Bainbridge794735f2020-02-11 21:01:37 -08001700func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301701 logger.Debugw("received-packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001702 "packet-indication": *packetIn,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001703 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001704 "packet": hex.EncodeToString(packetIn.Pkt),
1705 })
npujarec5762e2020-01-01 14:08:48 +05301706 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001707 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001708 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001709 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301710 logger.Debugw("sending-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001711 "logicalPortNum": logicalPortNum,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001712 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001713 "packet": hex.EncodeToString(packetIn.Pkt),
1714 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001715 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301716 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001717 "destination": "core",
Thomas Lee S985938d2020-05-04 11:40:41 +05301718 "source": dh.device.Type,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001719 "device-id": dh.device.Id,
1720 "packet": hex.EncodeToString(packetIn.Pkt),
1721 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001722 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301723 logger.Debugw("success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001724 "packet": hex.EncodeToString(packetIn.Pkt),
Thomas Lee S985938d2020-05-04 11:40:41 +05301725 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001726 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001727 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001728}
1729
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001730// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301731func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001732 logger.Debugw("incoming-packet-out", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301733 "device-id": dh.device.Id,
Shrey Baid807a2a02020-04-09 12:52:45 +05301734 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001735 "pkt-length": len(packet.Data),
1736 "packet": hex.EncodeToString(packet.Data),
1737 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001738
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001739 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001740 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001741 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1742 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301743 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1744 // Do not packet-out lldp packets on uni port.
1745 // ONOS has no clue about uni/nni ports, it just packets out on all
1746 // available ports on the Logical Switch. It should not be interested
1747 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001748 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1749 "device-id": dh.device.Id,
1750 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301751 return nil
1752 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001753 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1754 if innerEthType == 0x8100 {
1755 // q-in-q 802.1ad or 802.1q double tagged packet.
1756 // slice out the outer tag.
1757 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001758 logger.Debugw("packet-now-single-tagged", log.Fields{
1759 "packetData": hex.EncodeToString(packet.Data),
1760 "device-id": dh.device.Id,
1761 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001762 }
1763 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001764 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1765 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001766 uniID := UniIDFromPortNum(uint32(egressPortNo))
1767
npujarec5762e2020-01-01 14:08:48 +05301768 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001769 if err != nil {
1770 // In this case the openolt agent will receive the gemPortID as 0.
1771 // The agent tries to retrieve the gemPortID in this case.
1772 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001773 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001774 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301775 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001776 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001777 }
1778
1779 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001780
Girish Kumar2ad402b2020-03-20 19:45:12 +00001781 logger.Debugw("sending-packet-to-onu", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301782 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001783 "IntfId": intfID,
1784 "onuID": onuID,
1785 "uniID": uniID,
1786 "gemPortID": gemPortID,
1787 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301788 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001789 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001790
npujarec5762e2020-01-01 14:08:48 +05301791 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301792 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001793 "source": "adapter",
1794 "destination": "onu",
1795 "egress-port-number": egressPortNo,
1796 "interface-id": intfID,
1797 "oni-id": onuID,
1798 "uni-id": uniID,
1799 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001800 "packet": hex.EncodeToString(packet.Data),
1801 "device-id": dh.device.Id,
1802 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001803 }
1804 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001805 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1806 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001807 return olterrors.NewErrInvalidValue(log.Fields{
1808 "egress-nni-port": egressPortNo,
1809 "device-id": dh.device.Id,
1810 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001811 }
1812 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001813
Girish Kumar2ad402b2020-03-20 19:45:12 +00001814 logger.Debugw("sending-packet-to-nni", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301815 "uplink-pkt": uplinkPkt,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001816 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301817 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001818 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001819
npujarec5762e2020-01-01 14:08:48 +05301820 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001821 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1822 "packet": hex.EncodeToString(packet.Data),
1823 "device-id": dh.device.Id,
1824 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001825 }
1826 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301827 logger.Warnw("packet-out-to-this-interface-type-not-implemented", log.Fields{
1828 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001829 "egressPortType": egressPortType,
1830 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301831 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001832 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001833 }
1834 return nil
1835}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001836
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001837func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1838 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001839}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301840
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001841func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301842 // start the heartbeat check towards the OLT.
1843 var timerCheck *time.Timer
1844
1845 for {
1846 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1847 select {
1848 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001849 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1850 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301851 logger.Warnw("hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301852 if timerCheck == nil {
1853 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001854 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301855 }
1856 } else {
1857 if timerCheck != nil {
1858 if timerCheck.Stop() {
Thomas Lee S985938d2020-05-04 11:40:41 +05301859 logger.Debugw("got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301860 }
1861 timerCheck = nil
1862 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301863 logger.Debugw("hearbeat",
1864 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301865 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301866 }
1867 cancel()
1868 case <-dh.stopHeartbeatCheck:
Thomas Lee S985938d2020-05-04 11:40:41 +05301869 logger.Debugw("stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301870 return
1871 }
1872 }
1873}
1874
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001875func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1876 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1877 if err != nil || device == nil {
1878 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1879 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301880
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001881 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1882 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1883 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1884 }
1885 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1886 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1887 }
1888 go dh.cleanupDeviceResources(ctx)
1889
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001890 dh.lockDevice.RLock()
1891 // Stop the read indication only if it the routine is active
1892 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1893 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1894 // on next execution of the readIndication routine.
1895 if dh.isReadIndicationRoutineActive {
1896 dh.stopIndications <- true
1897 }
1898 dh.lockDevice.RUnlock()
1899
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001900 dh.transitionMap.Handle(ctx, DeviceInit)
1901
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301902 }
1903}
kesavand39e0aa32020-01-28 20:58:50 -05001904
1905// EnablePort to enable Pon interface
1906func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001907 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001908 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001909}
1910
1911// DisablePort to disable pon interface
1912func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001913 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001914 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001915}
1916
kdarapu1afeceb2020-02-12 01:38:09 -05001917//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1918func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301919 ctx := context.Background()
Thomas Lee S985938d2020-05-04 11:40:41 +05301920 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05001921 if port.GetType() == voltha.Port_ETHERNET_NNI {
1922 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001923 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301924 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301925 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001926 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001927 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001928 }
1929 // fetch interfaceid from PortNo
1930 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1931 ponIntf := &oop.Interface{IntfId: ponID}
1932 var operStatus voltha.OperStatus_Types
1933 if enablePort {
1934 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301935 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001936
1937 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301938 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001939 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001940 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001941 }
1942 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001943 dh.activePorts.Store(ponID, true)
Shrey Baid807a2a02020-04-09 12:52:45 +05301944 logger.Infow("enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001945 } else {
1946 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301947 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001948 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301949 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001950 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001951 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001952 }
1953 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001954 dh.activePorts.Store(ponID, false)
Shrey Baid807a2a02020-04-09 12:52:45 +05301955 logger.Infow("disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001956 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301957 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 +05301958 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301959 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001960 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001961 }
1962 return nil
1963}
1964
kdarapu1afeceb2020-02-12 01:38:09 -05001965//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1966func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001967 cloned := proto.Clone(device).(*voltha.Device)
1968 // Disable the port and update the oper_port_status to core
1969 // if the Admin state of the port is disabled on reboot and re-enable device.
1970 for _, port := range cloned.Ports {
1971 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001972 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301973 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301974 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001975 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001976 }
1977 }
1978 }
1979 return nil
1980}
1981
1982//populateActivePorts to populate activePorts map
1983func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301984 logger.Infow("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001985 for _, port := range device.Ports {
1986 if port.Type == voltha.Port_ETHERNET_NNI {
1987 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001988 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001989 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001990 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001991 }
1992 }
1993 if port.Type == voltha.Port_PON_OLT {
1994 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001995 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001996 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001997 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001998 }
1999 }
2000 }
2001}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002002
2003// ChildDeviceLost deletes ONU and clears pon resources related to it.
2004func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002005 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002006 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2007 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002008 onuDevice, ok := dh.onus.Load(onuKey)
2009 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302010 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002011 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302012 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002013 "onu-id": onuID,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002014 "interface-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002015 }
2016 var sn *oop.SerialNumber
2017 var err error
2018 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302019 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002020 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302021 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002022 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2023 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002024
2025 for uniID := 0; uniID < MaxUnisPerOnu; uniID++ {
2026 var flowRemoveData pendingFlowRemoveData
2027 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uint32(uniID)}
2028 dh.lockDevice.RLock()
2029 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2030 dh.lockDevice.RUnlock()
2031 continue
2032 }
2033 dh.lockDevice.RUnlock()
2034
2035 log.Debugw("wait-for-flow-remove-complete-before-processing-child-device-lost",
2036 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2037 // Wait for all flow removes to finish first
2038 <-flowRemoveData.allFlowsRemoved
2039 log.Debugw("flow-removes-complete-for-subscriber",
2040 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2041 }
2042
2043 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002044 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302045 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302046 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002047 "onu-id": onuID}, err).Log()
2048 }
2049 //clear PON resources associated with ONU
2050 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002051 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002052 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302053 "device-id": dh.device.Id,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002054 "interface-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002055 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002056 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05302057 logger.Warnw("failed-to-get-onu-info-for-pon-port", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302058 "device-id": dh.device.Id,
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002059 "interface-id": intfID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002060 "error": err})
2061 } else {
2062 for i, onu := range onuGemData {
2063 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Shrey Baid807a2a02020-04-09 12:52:45 +05302064 logger.Debugw("onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002065 if err := dh.clearUNIData(ctx, &onu); err != nil {
2066 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302067 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002068 "onu-device": onu,
2069 "error": err})
2070 }
2071 // Clear flowids for gem cache.
2072 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002073 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002074 }
2075 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002076 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002077 if err != nil {
2078 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002079 "interface-id": intfID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002080 "onu-device": onu,
2081 "onu-gem": onuGemData,
2082 "error": err})
2083 //Not returning error on cleanup.
2084 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002085 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
2086 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002087 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002088 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002089 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002090 }
2091 }
2092 dh.onus.Delete(onuKey)
2093 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2094 return nil
2095}
Girish Gowdracefae192020-03-19 18:14:10 -07002096
2097func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2098 for _, field := range flows.GetOfbFields(flow) {
2099 if field.Type == flows.IN_PORT {
2100 return field.GetPort()
2101 }
2102 }
2103 return InvalidPort
2104}
2105
2106func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2107 for _, action := range flows.GetActions(flow) {
2108 if action.Type == flows.OUTPUT {
2109 if out := action.GetOutput(); out != nil {
2110 return out.GetPort()
2111 }
2112 }
2113 }
2114 return InvalidPort
2115}
2116
2117func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2118 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302119 logger.Debugw("increment-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002120 if inPort != InvalidPort && outPort != InvalidPort {
2121 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2122 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302123 logger.Debugw("increment-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002124
2125 dh.lockDevice.Lock()
2126 defer dh.lockDevice.Unlock()
2127 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2128 if !ok {
2129 flowRemoveData = pendingFlowRemoveData{
2130 pendingFlowRemoveCount: 0,
2131 allFlowsRemoved: make(chan struct{}),
2132 }
2133 }
2134 flowRemoveData.pendingFlowRemoveCount++
2135 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2136
Shrey Baid807a2a02020-04-09 12:52:45 +05302137 logger.Debugw("current-flow-remove-count–increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002138 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2139 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2140 }
2141}
2142
2143func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2144 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302145 logger.Debugw("decrement-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002146 if inPort != InvalidPort && outPort != InvalidPort {
2147 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2148 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302149 logger.Debugw("decrement-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002150
2151 dh.lockDevice.Lock()
2152 defer dh.lockDevice.Unlock()
2153 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302154 logger.Fatalf("flow-remove-key-not-found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002155 } else {
2156 if val.pendingFlowRemoveCount > 0 {
2157 val.pendingFlowRemoveCount--
2158 }
Shrey Baid807a2a02020-04-09 12:52:45 +05302159 logger.Debugw("current-flow-remove-count-after-decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002160 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2161 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2162 // If all flow removes have finished, then close the channel to signal the receiver
2163 // to go ahead with flow adds.
2164 if val.pendingFlowRemoveCount == 0 {
2165 close(val.allFlowsRemoved)
2166 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2167 return
2168 }
2169 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2170 }
2171 }
2172}
2173
2174func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2175 var flowRemoveData pendingFlowRemoveData
2176 var ok bool
2177 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302178 logger.Debugw("wait-for-flow-remove-to-finish-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002179 if inPort != InvalidPort && outPort != InvalidPort {
2180 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2181 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302182 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 -07002183
2184 dh.lockDevice.RLock()
2185 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302186 logger.Debugw("no-pending-flow-to-remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002187 dh.lockDevice.RUnlock()
2188 return
2189 }
2190 dh.lockDevice.RUnlock()
2191
2192 // Wait for all flow removes to finish first
2193 <-flowRemoveData.allFlowsRemoved
2194
Shrey Baid807a2a02020-04-09 12:52:45 +05302195 logger.Debugw("all-flows-cleared--handling-flow-add-now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002196 }
2197}
2198
2199func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2200 inPort := getInPortFromFlow(flow)
2201 outPort := getOutPortFromFlow(flow)
2202
2203 if inPort == InvalidPort || outPort == InvalidPort {
2204 return inPort, outPort
2205 }
2206
2207 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2208 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2209 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2210 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2211 return uniPort, outPort
2212 }
2213 }
2214 } else {
2215 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2216 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2217 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2218 return inPort, uniPort
2219 }
2220 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2221 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2222 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2223 return uniPort, outPort
2224 }
2225 }
2226 }
2227
2228 return InvalidPort, InvalidPort
2229}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002230
2231func extractOmciTransactionID(omciPkt []byte) uint16 {
2232 if len(omciPkt) > 3 {
2233 d := omciPkt[0:2]
2234 transid := binary.BigEndian.Uint16(d)
2235 return transid
2236 }
2237 return 0
2238}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002239
2240// StoreOnuDevice stores the onu parameters to the local cache.
2241func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2242 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2243 dh.onus.Store(onuKey, onuDevice)
2244}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002245
Devmalya Paula1efa642020-04-20 01:36:43 -04002246// setOnuITUPonAlarmConfig sets the parameters in the openolt agent for raising the ONU ITU PON alarms.
2247func (dh *DeviceHandler) setOnuITUPonAlarmConfig(config *oop.OnuItuPonAlarm) error {
2248 if _, err := dh.Client.OnuItuPonAlarmSet(context.Background(), config); err != nil {
2249 return err
2250 }
2251 logger.Debugw("onu-itu-pon-alarm-config-set-successful", log.Fields{"config": config})
2252 return nil
2253}
2254
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002255func (dh *DeviceHandler) getExtValue(device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
2256 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002257 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002258 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002259 resp := new(voltha.ReturnValues)
2260 valueparam := new(oop.ValueParam)
2261 ctx := context.Background()
2262 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002263 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2264 return nil, err
2265 }
2266 ID = device.ProxyAddress.GetOnuId()
2267 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2268 valueparam.Onu = &Onu
2269 valueparam.Value = value
2270
2271 // This API is unsupported until agent patch is added
2272 resp.Unsupported = uint32(value)
2273 _ = ctx
2274
2275 // Uncomment this code once agent changes are complete and tests
2276 /*
2277 resp, err = dh.Client.GetValue(ctx, valueparam)
2278 if err != nil {
2279 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2280 return nil, err
2281 }
2282 */
2283
2284 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2285 return resp, nil
2286}