blob: 1390e1d3f067a41411f165c4222620e2a54cbabe [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneret1359c732019-08-01 21:40:02 -040022 "encoding/hex"
cuilin20187b2a8c32019-03-26 19:52:28 -070023 "fmt"
Girish Gowdracefae192020-03-19 18:14:10 -070024 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
cuilin20187b2a8c32019-03-26 19:52:28 -070025 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040026 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070027 "strconv"
28 "strings"
29 "sync"
30 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053031
Chaitrashree G Sb2b62dd2019-07-24 21:47:04 -040032 "google.golang.org/grpc/codes"
33
Matteo Scandolo945e4012019-12-12 14:16:11 -080034 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070035 "github.com/gogo/protobuf/proto"
36 "github.com/golang/protobuf/ptypes"
Esin Karamanccb714b2019-11-29 15:02:06 +000037 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
38 "github.com/opencord/voltha-lib-go/v3/pkg/log"
39 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Thomas Lee S94109f12020-03-03 16:39:29 +053040 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080041 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000042 "github.com/opencord/voltha-protos/v3/go/common"
43 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
44 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
45 oop "github.com/opencord/voltha-protos/v3/go/openolt"
46 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070047 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040048 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053049)
50
salmansiddiqui7ac62132019-08-22 03:58:50 +000051// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040052const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000053 MaxRetry = 10
54 MaxTimeOutInMs = 500
Girish Gowdracefae192020-03-19 18:14:10 -070055 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040056)
57
Girish Gowdracefae192020-03-19 18:14:10 -070058// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
59type pendingFlowRemoveDataKey struct {
60 intfID uint32
61 onuID uint32
62 uniID uint32
63}
64
65// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
66// This holds the number of pending flow removes and also a signal channel to
67// to indicate the receiver when all flow removes are handled
68type pendingFlowRemoveData struct {
69 pendingFlowRemoveCount uint32
70 allFlowsRemoved chan struct{}
71}
72
Phaneendra Manda4c62c802019-03-06 21:37:49 +053073//DeviceHandler will interact with the OLT device.
74type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070076 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040077 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070078 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053079 coreProxy adapterif.CoreProxy
80 AdapterProxy adapterif.AdapterProxy
81 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070082 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070083 exitChannel chan int
84 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053085 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070086 transitionMap *TransitionMap
87 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053088 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040089 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053090 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053091
Girish Gowdra3ab6d212020-03-24 17:33:15 -070092 discOnus sync.Map
93 onus sync.Map
94 portStats *OpenOltStatisticsMgr
95 metrics *pmmetrics.PmMetrics
96 stopCollector chan bool
97 stopHeartbeatCheck chan bool
98 activePorts sync.Map
99 stopIndications chan bool
100 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700101
102 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
103 // subscriber basis for the number of pending flow removes. This data is used
104 // to process all the flow removes for a subscriber before handling flow adds.
105 // Interleaving flow delete and flow add processing has known to cause PON resource
106 // management contentions on a per subscriber bases, so we need ensure ordering.
107 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700108}
109
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700111type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700113 deviceType string
114 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115 onuID uint32
116 intfID uint32
117 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +0000118 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530119 losRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700120}
121
Naga Manjunath7615e552019-10-11 22:35:47 +0530122var pmNames = []string{
123 "rx_bytes",
124 "rx_packets",
125 "rx_mcast_packets",
126 "rx_bcast_packets",
127 "tx_bytes",
128 "tx_packets",
129 "tx_mcast_packets",
130 "tx_bcast_packets",
131}
132
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700133//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530134func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700135 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700136 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700137 device.deviceType = deviceTp
138 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700139 device.onuID = onuID
140 device.intfID = intfID
141 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000142 device.uniPorts = make(map[uint32]struct{})
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530143 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700144 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530145}
146
147//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530148func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700149 var dh DeviceHandler
150 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400151 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400152 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700153 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700154 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700155 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400156 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700157 dh.device = cloned
158 dh.openOLT = adapter
159 dh.exitChannel = make(chan int, 1)
160 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530161 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530162 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530163 dh.metrics = pmmetrics.NewPmMetrics(cloned.Id, pmmetrics.Frequency(150), pmmetrics.FrequencyOverride(false), pmmetrics.Grouped(false), pmmetrics.Metrics(pmNames))
Chaitrashree G Sef088112020-02-03 21:39:27 -0500164 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400165 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700166 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
167
cuilin20187b2a8c32019-03-26 19:52:28 -0700168 //TODO initialize the support classes.
169 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530170}
171
172// start save the device to the data model
173func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700174 dh.lockDevice.Lock()
175 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000176 logger.Debugw("starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700177 // Add the initial device to the local model
Girish Kumar2ad402b2020-03-20 19:45:12 +0000178 logger.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530179}
180
181// stop stops the device dh. Not much to do for now
182func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700183 dh.lockDevice.Lock()
184 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000185 logger.Debug("stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700186 dh.exitChannel <- 1
Girish Kumar2ad402b2020-03-20 19:45:12 +0000187 logger.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530188}
189
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400190func macifyIP(ip net.IP) string {
191 if len(ip) > 0 {
192 oct1 := strconv.FormatInt(int64(ip[12]), 16)
193 oct2 := strconv.FormatInt(int64(ip[13]), 16)
194 oct3 := strconv.FormatInt(int64(ip[14]), 16)
195 oct4 := strconv.FormatInt(int64(ip[15]), 16)
196 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
197 }
198 return ""
199}
200
201func generateMacFromHost(host string) (string, error) {
202 var genmac string
203 var addr net.IP
204 var ips []string
205 var err error
206
Girish Kumar2ad402b2020-03-20 19:45:12 +0000207 logger.Debugw("generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400208
209 if addr = net.ParseIP(host); addr == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000210 logger.Debugw("looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400211
212 if ips, err = net.LookupHost(host); err == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000213 logger.Debugw("dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400214 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000215 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400216 }
217 genmac = macifyIP(addr)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000218 logger.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400219 return genmac, nil
220 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000221 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400222 }
223
224 genmac = macifyIP(addr)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000225 logger.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400226 return genmac, nil
227}
228
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530229func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700230 slist := strings.Split(mac, ":")
231 result := make([]uint32, len(slist))
232 var err error
233 var tmp int64
234 for index, val := range slist {
235 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
236 return []uint32{1, 2, 3, 4, 5, 6}
237 }
238 result[index] = uint32(tmp)
239 }
240 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530241}
242
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700243//GetportLabel returns the label for the NNI and the PON port based on port number and port type
David K. Bainbridge794735f2020-02-11 21:01:37 -0800244func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530245
David K. Bainbridge794735f2020-02-11 21:01:37 -0800246 switch portType {
247 case voltha.Port_ETHERNET_NNI:
248 return fmt.Sprintf("nni-%d", portNum), nil
249 case voltha.Port_PON_OLT:
250 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700251 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800252
Girish Kumarf26e4882020-03-05 06:49:10 +0000253 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530254}
255
David K. Bainbridge794735f2020-02-11 21:01:37 -0800256func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000257 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700258 if state == "up" {
259 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500260 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500261 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700262 } else {
263 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500264 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700265 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700266 portNum := IntfIDToPortNo(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800267 label, err := GetportLabel(portNum, portType)
268 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000269 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400270 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500271
272 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
273 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000274 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500275 }
276 if device.Ports != nil {
277 for _, dPort := range device.Ports {
278 if dPort.Type == portType && dPort.PortNo == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000279 logger.Debug("port-already-exists-updating-oper-status-of-port")
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500280 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530281 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800282 "device-id": dh.device.Id,
283 "port-type": portType,
284 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000285 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800286
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500287 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800288 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500289 }
290 }
291 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400292 // Now create Port
293 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700294 PortNo: portNum,
295 Label: label,
296 Type: portType,
297 OperStatus: operStatus,
298 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000299 logger.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700300 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700301 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000302 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800303 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000304 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400305 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800306 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530307}
308
309// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800310func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000311 defer logger.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700312 defer func() {
313 dh.lockDevice.Lock()
314 dh.isReadIndicationRoutineActive = false
315 dh.lockDevice.Unlock()
316 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700317 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700318 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700319 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700320 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400321 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530322 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400323 if err != nil || device == nil {
324 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000325 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400326 }
327 // When the device is in DISABLED and Adapter container restarts, we need to
328 // rebuild the locally maintained admin state.
329 if device.AdminState == voltha.AdminState_DISABLED {
330 dh.lockDevice.Lock()
331 dh.adminState = "down"
332 dh.lockDevice.Unlock()
333 }
334
David Bainbridgef5879ca2019-12-13 21:17:54 +0000335 // Create an exponential backoff around re-enabling indications. The
336 // maximum elapsed time for the back off is set to 0 so that we will
337 // continue to retry. The max interval defaults to 1m, but is set
338 // here for code clarity
339 indicationBackoff := backoff.NewExponentialBackOff()
340 indicationBackoff.MaxElapsedTime = 0
341 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700342
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700343 dh.lockDevice.Lock()
344 dh.isReadIndicationRoutineActive = true
345 dh.lockDevice.Unlock()
346
Girish Gowdra3f974912020-03-23 20:35:18 -0700347Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700348 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400349 select {
350 case <-dh.stopIndications:
Girish Kumar2ad402b2020-03-20 19:45:12 +0000351 logger.Debugw("Stopping-collecting-indications-for-OLT", log.Fields{"deviceID:": dh.deviceID})
Girish Gowdra3f974912020-03-23 20:35:18 -0700352 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400353 default:
354 indication, err := indications.Recv()
355 if err == io.EOF {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000356 logger.Infow("EOF for indications", log.Fields{"err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400357 // Use an exponential back off to prevent getting into a tight loop
358 duration := indicationBackoff.NextBackOff()
359 if duration == backoff.Stop {
360 // If we reach a maximum then warn and reset the backoff
361 // timer and keep attempting.
Girish Kumar2ad402b2020-03-20 19:45:12 +0000362 logger.Warnw("Maximum indication backoff reached, resetting backoff timer",
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400363 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
364 indicationBackoff.Reset()
365 }
366 time.Sleep(indicationBackoff.NextBackOff())
Girish Gowdra3f974912020-03-23 20:35:18 -0700367 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
368 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400369 }
370 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000371 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530372 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700373 logger.Errorw("Read indication error", log.Fields{"err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400374 if dh.adminState == "deleted" {
Girish Gowdra3f974912020-03-23 20:35:18 -0700375 logger.Debug("Device deleted stopping the read indication thread")
376 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400377 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700378 // Close the stream, and re-initialize it
379 if err = indications.CloseSend(); err != nil {
380 // Ok to ignore here, because we landed here due to a problem on the stream
381 // In all probability, the closeSend call may fail
382 logger.Debugw("error closing send stream, error ignored", log.Fields{"err": err})
383 }
384 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
385 return err
386 }
387 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400388 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530389 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400390 // Reset backoff if we have a successful receive
391 indicationBackoff.Reset()
392 dh.lockDevice.RLock()
393 adminState := dh.adminState
394 dh.lockDevice.RUnlock()
395 // When OLT is admin down, ignore all indications.
396 if adminState == "down" && !isIndicationAllowedDuringOltAdminDown(indication) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000397 logger.Debugw("olt is admin down, ignore indication", log.Fields{"indication": indication})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400398 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400399 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400400 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700401 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700402 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700403 // Close the send stream
404 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700405
Girish Gowdra3f974912020-03-23 20:35:18 -0700406 return nil
407}
408
409func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
410
411 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
412 if err != nil {
413 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
414 }
415 if indications == nil {
416 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
417 }
418
419 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400420}
421
422// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
423func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
424 switch indication.Data.(type) {
425 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
426 return true
427
428 default:
429 return false
430 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700431}
432
David K. Bainbridge794735f2020-02-11 21:01:37 -0800433func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000434 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000435 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530436 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700437 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530438 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700439 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000440 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800441 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530442 return olterrors.NewErrAdapter("failed-indication", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800443 "device_id": dh.deviceID,
444 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000445 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800446 }
447 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700448}
449
David K. Bainbridge794735f2020-02-11 21:01:37 -0800450// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530451func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400452 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700453 switch indication.Data.(type) {
454 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800455 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530456 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800457 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700458 case *oop.Indication_IntfInd:
459 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800460 go func() {
461 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530462 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800463 }
464 }()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000465 logger.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700466 case *oop.Indication_IntfOperInd:
467 intfOperInd := indication.GetIntfOperInd()
468 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800469 go func() {
470 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530471 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800472 }
473 }()
npujarec5762e2020-01-01 14:08:48 +0530474 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700475 } else if intfOperInd.GetType() == "pon" {
476 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
477 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800478 go func() {
479 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530480 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 }
482 }()
kesavand39e0aa32020-01-28 20:58:50 -0500483 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700484 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000485 logger.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700486 case *oop.Indication_OnuDiscInd:
487 onuDiscInd := indication.GetOnuDiscInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000488 logger.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700489 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800490 go func() {
491 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530492 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800493 }
494 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700495 case *oop.Indication_OnuInd:
496 onuInd := indication.GetOnuInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000497 logger.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800498 go func() {
499 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530500 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800501 }
502 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700503 case *oop.Indication_OmciInd:
504 omciInd := indication.GetOmciInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000505 logger.Debugw("Received Omci indication ", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "pkt": hex.EncodeToString(omciInd.Pkt)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800506 go func() {
507 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530508 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800509 }
510 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700511 case *oop.Indication_PktInd:
512 pktInd := indication.GetPktInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000513 logger.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800514 go func() {
515 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530516 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800517 }
518 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700519 case *oop.Indication_PortStats:
520 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530521 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700522 case *oop.Indication_FlowStats:
523 flowStats := indication.GetFlowStats()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000524 logger.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525 case *oop.Indication_AlarmInd:
526 alarmInd := indication.GetAlarmInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000527 logger.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530528 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700529 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530530}
531
532// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530533func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400534 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530535 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400536 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000537 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400538 }
539 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530540}
541
542// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530543func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700544 dh.lockDevice.Lock()
545 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000546 logger.Debug("do-state-down-start")
Girish Gowdrud4245152019-05-10 00:47:31 -0400547
npujarec5762e2020-01-01 14:08:48 +0530548 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400549 if err != nil || device == nil {
550 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000551 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400552 }
553
554 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400555
556 //Update the device oper state and connection status
557 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400558 dh.device = cloned
559
David K. Bainbridge794735f2020-02-11 21:01:37 -0800560 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000561 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400562 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400563
564 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530565 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400566 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000567 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400568 }
569 for _, onuDevice := range onuDevices.Items {
570
571 // Update onu state as down in onu adapter
572 onuInd := oop.OnuIndication{}
573 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800574 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700575 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800576 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530577 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800578 "source": "openolt",
579 "onu-indicator": onuInd,
580 "device-type": onuDevice.Type,
581 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700582 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700583 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400584 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700585 /* Discovered ONUs entries need to be cleared , since after OLT
586 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530587 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000588 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700589 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530590}
591
592// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530593func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400594 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800595 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530596 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800597 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000598 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400599 }
600 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530601}
602
603// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530604func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400605 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530606 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400607 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530608}
609
610// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530611func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000612 logger.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400613
614 // Case where OLT is disabled and then rebooted.
615 if dh.adminState == "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000616 logger.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530617 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400618 if err != nil || device == nil {
619 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530620 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400621 }
622
623 cloned := proto.Clone(device).(*voltha.Device)
624 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
625 cloned.OperStatus = voltha.OperStatus_UNKNOWN
626 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530627 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530628 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400629 }
630
Chaitrashree G S44124192019-08-07 20:21:36 -0400631 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
npujarec5762e2020-01-01 14:08:48 +0530632 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400633 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530634 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400635 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400636 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
637 // all the modules initialized and ready to handle incoming ONUs.
638
639 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
640 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
641 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400642
643 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800644 go func() {
645 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530646 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800647 }
648 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400649 return nil
650 }
651
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700652 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400653 if err != nil || device == nil {
654 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000655 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400656 }
kesavand39e0aa32020-01-28 20:58:50 -0500657 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500658 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000659 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400660 }
661
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400662 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
663 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400664 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530665
cuilin20187b2a8c32019-03-26 19:52:28 -0700666 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800667 go func() {
668 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530669 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800670 }
671 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700672 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530673}
674
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400675func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
676 deviceInfo, err := dh.populateDeviceInfo()
677
678 if err != nil {
679 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
680 }
681 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
682 // Instantiate resource manager
683 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
684 return olterrors.ErrResourceManagerInstantiating
685 }
686
687 // Instantiate flow manager
688 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
689 return olterrors.ErrResourceManagerInstantiating
690
691 }
692 /* TODO: Instantiate Alarm , stats , BW managers */
693 /* Instantiating Event Manager to handle Alarms and KPIs */
694 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
695
696 // Stats config for new device
697 dh.portStats = NewOpenOltStatsMgr(dh)
698
699 return nil
700
701}
702
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400703func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
704 var err error
705 var deviceInfo *oop.DeviceInfo
706
707 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
708
709 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000710 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400711 }
712 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000713 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400714 }
715
Girish Kumar2ad402b2020-03-20 19:45:12 +0000716 logger.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400717 dh.device.Root = true
718 dh.device.Vendor = deviceInfo.Vendor
719 dh.device.Model = deviceInfo.Model
720 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
721 dh.device.HardwareVersion = deviceInfo.HardwareVersion
722 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
723
724 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000725 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400726 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
727 genmac, err := generateMacFromHost(host)
728 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000729 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400730 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000731 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400732 dh.device.MacAddress = genmac
733 } else {
734 dh.device.MacAddress = deviceInfo.DeviceId
735 }
736
737 // Synchronous call to update device - this method is run in its own go routine
738 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000739 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400740 }
741
742 return deviceInfo, nil
743}
744
Naga Manjunath7615e552019-10-11 22:35:47 +0530745func startCollector(dh *DeviceHandler) {
746 // Initial delay for OLT initialization
747 time.Sleep(1 * time.Minute)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000748 logger.Debugf("Starting-Collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530749 context := make(map[string]string)
750 for {
751 select {
752 case <-dh.stopCollector:
Girish Kumar2ad402b2020-03-20 19:45:12 +0000753 logger.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
Naga Manjunath7615e552019-10-11 22:35:47 +0530754 return
755 default:
756 freq := dh.metrics.ToPmConfigs().DefaultFreq
757 time.Sleep(time.Duration(freq) * time.Second)
758 context["oltid"] = dh.deviceID
759 context["devicetype"] = dh.deviceType
760 // NNI Stats
761 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
Girish Kumar2ad402b2020-03-20 19:45:12 +0000762 logger.Debugf("Collect-NNI-Metrics %v", cmnni)
Naga Manjunath7615e552019-10-11 22:35:47 +0530763 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000764 logger.Debugf("Publish-NNI-Metrics")
Naga Manjunath7615e552019-10-11 22:35:47 +0530765 // PON Stats
766 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500767 for i := uint32(0); i < NumPonPORTS; i++ {
768 if val, ok := dh.activePorts.Load(i); ok && val == true {
769 cmpon := dh.portStats.collectPONMetrics(i)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000770 logger.Debugf("Collect-PON-Metrics %v", cmpon)
Naga Manjunath7615e552019-10-11 22:35:47 +0530771
Chaitrashree G Sef088112020-02-03 21:39:27 -0500772 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000773 logger.Debugf("Publish-PON-Metrics")
Chaitrashree G Sef088112020-02-03 21:39:27 -0500774 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530775 }
776 }
777 }
778}
779
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700780//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530781func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400782 dh.transitionMap = NewTransitionMap(dh)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000783 logger.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530784 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530785
786 // Now, set the initial PM configuration for that device
787 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530788 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530789 }
790
791 go startCollector(dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400792 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530793}
794
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700795//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530796func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700797 return &ic.SwitchCapability{
798 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530799 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700800 HwDesc: "open_pon",
801 SwDesc: "open_pon",
802 SerialNum: dh.device.SerialNumber,
803 },
804 SwitchFeatures: &of.OfpSwitchFeatures{
805 NBuffers: 256,
806 NTables: 2,
807 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
808 of.OfpCapabilities_OFPC_TABLE_STATS |
809 of.OfpCapabilities_OFPC_PORT_STATS |
810 of.OfpCapabilities_OFPC_GROUP_STATS),
811 },
812 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530813}
814
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700815//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530816func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700817 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700818 return &ic.PortCapability{
819 Port: &voltha.LogicalPort{
820 OfpPort: &of.OfpPort{
821 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
822 Config: 0,
823 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700824 Curr: capacity,
825 Advertised: capacity,
826 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700827 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
828 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
829 },
830 DeviceId: dh.device.Id,
831 DevicePortNo: uint32(portNo),
832 },
833 }, nil
834}
835
David K. Bainbridge794735f2020-02-11 21:01:37 -0800836func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000837 logger.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700838 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700839 var deviceID string
840 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700841
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700842 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530843
844 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
845
Girish Kumar2ad402b2020-03-20 19:45:12 +0000846 logger.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700847 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700848 kwargs := make(map[string]interface{})
849 kwargs["onu_id"] = omciInd.OnuId
850 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700851
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700852 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
853 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530854 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800855 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000856 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700857 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700858 deviceType = onuDevice.Type
859 deviceID = onuDevice.Id
860 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
861 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530862 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700863 } else {
864 //found in cache
Girish Kumar2ad402b2020-03-20 19:45:12 +0000865 logger.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530866 deviceType = onuInCache.(*OnuDevice).deviceType
867 deviceID = onuInCache.(*OnuDevice).deviceID
868 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700869 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700870
871 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800872 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700873 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800874 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530875 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800876 "source": dh.deviceType,
877 "destination": deviceType,
878 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000879 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700880 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800881 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530882}
883
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700884//ProcessInterAdapterMessage sends the proxied messages to the target device
885// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
886// is meant, and then send the unmarshalled omci message to this onu
887func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000888 logger.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700889 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700890 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700891 fromTopic := msg.Header.FromTopic
892 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700893 toDeviceID := msg.Header.ToDeviceId
894 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700895
Girish Kumar2ad402b2020-03-20 19:45:12 +0000896 logger.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700897
898 msgBody := msg.GetBody()
899
900 omciMsg := &ic.InterAdapterOmciMessage{}
901 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000902 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700903 }
904
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700905 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700906 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
907 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530908 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800909 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000910 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700911 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000912 logger.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800913 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530914 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800915 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000916 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800917 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700918 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000919 logger.Debugw("Proxy Address found in omci message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800920 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530921 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800922 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000923 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800924 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700925 }
926
927 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000928 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700929 }
930 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530931}
932
David K. Bainbridge794735f2020-02-11 21:01:37 -0800933func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700934 var intfID uint32
935 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000936 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700937 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938 intfID = onuDevice.ProxyAddress.GetChannelId()
939 onuID = onuDevice.ProxyAddress.GetOnuId()
940 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700941 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 intfID = omciMsg.GetProxyAddress().GetChannelId()
943 onuID = omciMsg.GetProxyAddress().GetOnuId()
944 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700945 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700946 if connectStatus != voltha.ConnectStatus_REACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000947 logger.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800948
Thomas Lee S94109f12020-03-03 16:39:29 +0530949 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800950 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000951 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700952 }
953
lcuie24ef182019-04-29 22:58:36 -0700954 // TODO: Once we are sure openonu/openomci is sending only binary in omciMsg.Message, we can remove this check
955 isHexString := false
956 _, decodeerr := hex.DecodeString(string(omciMsg.Message))
957 if decodeerr == nil {
958 isHexString = true
959 }
960
961 // TODO: OpenOLT Agent expects a hex string for OMCI packets rather than binary. Fix this in the agent and then we can pass binary Pkt: omciMsg.Message.
962 var omciMessage *oop.OmciMsg
963 if isHexString {
964 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: omciMsg.Message}
965 } else {
966 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
967 hex.Encode(hexPkt, omciMsg.Message)
968 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
969 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700970
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700971 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
972 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530973 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800974 "interface-id": intfID,
975 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000976 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700977 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000978 logger.Debugw("Sent Omci message", log.Fields{"intfID": intfID, "onuID": onuID, "omciMsg": hex.EncodeToString(omciMsg.Message)})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800979 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700980}
981
David K. Bainbridge794735f2020-02-11 21:01:37 -0800982func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000983 logger.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
Andrea Campanellab83b39d2020-03-30 11:41:16 +0200984 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
985 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
986 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700987 // TODO: need resource manager
988 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700989 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530990 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400991 st, _ := status.FromError(err)
992 if st.Code() == codes.AlreadyExists {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000993 logger.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400994 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000995 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400996 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700997 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000998 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
cuilin20187b2a8c32019-03-26 19:52:28 -0700999 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001000 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001001}
1002
David K. Bainbridge794735f2020-02-11 21:01:37 -08001003func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001004
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005 channelID := onuDiscInd.GetIntfId()
1006 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001007
Girish Kumar2ad402b2020-03-20 19:45:12 +00001008 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301009
cuilin20187b2a8c32019-03-26 19:52:28 -07001010 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001011 if sn != "" {
1012 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001013 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001014 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001015 }
1016
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301017 var alarmInd oop.OnuAlarmIndication
1018 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001019 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301020
1021 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1022 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1023 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1024 OnuLosRaise event sent for it */
1025 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1026 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1027 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001028 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301029 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1030 "currentIntfId": onuDiscInd.GetIntfId()})
1031 // TODO:: Should we need to ignore raising OnuLosClear event
1032 // when onu connected to different PON?
1033 }
1034 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1035 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1036 alarmInd.LosStatus = statusCheckOff
1037 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1038 }
1039 return true
1040 })
1041
Girish Kumar2ad402b2020-03-20 19:45:12 +00001042 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001044 }
1045
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001046 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001047
1048 // check the ONU is already know to the OLT
1049 // NOTE the second time the ONU is discovered this should return a device
1050 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1051
1052 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001053 logger.Warnw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001054 if e, ok := status.FromError(err); ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001055 logger.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001056 switch e.Code() {
1057 case codes.Internal:
1058 // this probably means NOT FOUND, so just create a new device
1059 onuDevice = nil
1060 case codes.DeadlineExceeded:
1061 // if the call times out, cleanup and exit
1062 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001063 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001064 }
1065 }
1066 }
1067
1068 if onuDevice == nil {
1069 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Girish Kumar2ad402b2020-03-20 19:45:12 +00001070 logger.Infow("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001071 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001072 ponintfid := onuDiscInd.GetIntfId()
1073 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301074 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001075 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001076
Girish Kumar2ad402b2020-03-20 19:45:12 +00001077 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001078
1079 if err != nil {
1080 // if we can't create an ID in resource manager,
1081 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001082 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001083 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001084 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001085 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001086 }
1087
1088 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1089 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001090 dh.discOnus.Delete(sn)
1091 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 +05301092 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001094 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001095 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001096 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Girish Kumar2ad402b2020-03-20 19:45:12 +00001097 logger.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001098 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001099
1100 // we can now use the existing ONU Id
1101 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001102 //Insert the ONU into cache to use in OnuIndication.
1103 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001104 logger.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
Matteo Scandolo945e4012019-12-12 14:16:11 -08001105 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001106 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001107
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301108 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301109 dh.onus.Store(onuKey, onuDev)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001110 logger.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001111
David K. Bainbridge794735f2020-02-11 21:01:37 -08001112 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301113 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001114 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001115 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001116 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001117 logger.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001118 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301119 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001120 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001121 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001122 }
1123 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001124}
1125
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001127 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1128
1129 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001130 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001131 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001133 foundInCache := false
Girish Kumar2ad402b2020-03-20 19:45:12 +00001134 logger.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
Scott Baker7eb0a932019-07-26 10:33:22 -07001135 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001136 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301137
David K. Bainbridge794735f2020-02-11 21:01:37 -08001138 errFields := log.Fields{"device-id": dh.device.Id}
1139
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301140 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1141
Mahir Gunyele77977b2019-06-27 05:36:22 -07001142 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1143 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1145 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001146 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001147 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1148 if serialNumber != "" {
1149 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001150 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001151 } else {
1152 kwargs["onu_id"] = onuInd.OnuId
1153 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001154 errFields["onu-id"] = onuInd.OnuId
1155 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001156 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001158 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001159
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001161 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001162 }
1163
David K. Bainbridge794735f2020-02-11 21:01:37 -08001164 if onuDevice.ParentPortNo != ponPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001165 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001166 "previousIntfId": onuDevice.ParentPortNo,
1167 "currentIntfId": ponPort})
1168 }
1169
1170 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001171 logger.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001172 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1173 "received_onu_id": onuInd.OnuId})
1174 }
1175 if !foundInCache {
1176 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1177
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301178 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 -08001179
1180 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001181 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001182 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 }
1184 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001185}
1186
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001187func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301188 ctx := context.TODO()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001189 logger.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001190 if onuInd.AdminState == "down" {
1191 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1192 if onuInd.OperState != "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001193 logger.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001194 onuInd.OperState = "down"
1195 }
1196 }
1197
David K. Bainbridge794735f2020-02-11 21:01:37 -08001198 switch onuInd.OperState {
1199 case "down":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001200 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001201 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301202 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001203 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1204 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301205 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001206 "onu-indicator": onuInd,
1207 "source": "openolt",
1208 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001209 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001210 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001211 case "up":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001212 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Matt Jeanneret53539512019-07-20 14:47:02 -04001213 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301214 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001215 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1216 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301217 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 "onu-indicator": onuInd,
1219 "source": "openolt",
1220 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001221 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001222 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001223 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001224 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001225 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001226 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001227}
1228
cuilin20187b2a8c32019-03-26 19:52:28 -07001229func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1230 if serialNum != nil {
1231 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001232 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001233 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001234}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001235func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1236 decodedStr, err := hex.DecodeString(serialNum[4:])
1237 if err != nil {
1238 return nil, err
1239 }
1240 return &oop.SerialNumber{
1241 VendorId: []byte(serialNum[:4]),
1242 VendorSpecific: []byte(decodedStr),
1243 }, nil
1244}
cuilin20187b2a8c32019-03-26 19:52:28 -07001245
1246func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1247 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001248 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001249 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1250 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1251 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1252 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1253 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1254 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1255 return tmp
1256}
1257
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001258//UpdateFlowsBulk upates the bulk flow
1259func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301260 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001261}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001262
1263//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001265 logger.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001266 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001267 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001268 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001269 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001270 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001271 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001273 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001274 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001275 logger.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001276 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301277}
1278
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001279// SendPacketInToCore sends packet-in to core
1280// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1281// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001283 logger.Debugw("send-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001284 "port": logicalPort,
1285 "packet": hex.EncodeToString(packetPayload),
1286 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001287 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301288 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001289 "source": "adapter",
1290 "destination": "core",
1291 "device-id": dh.device.Id,
1292 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001293 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001294 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001295 logger.Debugw("Sent packet-in to core successfully", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001296 "packet": hex.EncodeToString(packetPayload),
1297 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001299}
1300
A R Karthick1f85b802019-10-11 05:06:05 +00001301// AddUniPortToOnu adds the uni port to the onu device
1302func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1303 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301304
1305 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001306 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301307 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1308 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001309 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001310 }
1311 }
1312}
1313
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001314//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301315func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001316 logger.Debugw("Received-incremental-flowupdate-in-device-handler", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001317
1318 var errorsList []error
1319
Girish Gowdru0c588b22019-04-23 23:24:56 -04001320 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001321 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001322 dh.incrementActiveFlowRemoveCount(flow)
1323
Girish Kumar2ad402b2020-03-20 19:45:12 +00001324 logger.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001325 err := dh.flowMgr.RemoveFlow(ctx, flow)
1326 if err != nil {
1327 errorsList = append(errorsList, err)
1328 }
1329
1330 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001331 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301332
1333 for _, flow := range flows.ToAdd.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001334 logger.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001335 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1336 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001337 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1338 if err != nil {
1339 errorsList = append(errorsList, err)
1340 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301341 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001342 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001343 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001344 for _, flow := range flows.ToRemove.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001345 logger.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001346 // dh.flowMgr.RemoveFlow(flow)
1347 }
1348 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001349
Girish Gowdracefae192020-03-19 18:14:10 -07001350 // 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 +00001351 if groups != nil {
1352 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001353 err := dh.flowMgr.AddGroup(ctx, group)
1354 if err != nil {
1355 errorsList = append(errorsList, err)
1356 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001357 }
1358 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001359 err := dh.flowMgr.ModifyGroup(ctx, group)
1360 if err != nil {
1361 errorsList = append(errorsList, err)
1362 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001363 }
1364 if len(groups.ToRemove.Items) != 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001365 logger.Debug("Group delete operation is not supported for now")
Esin Karamanccb714b2019-11-29 15:02:06 +00001366 }
1367 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001368 if len(errorsList) > 0 {
1369 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1370 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001371 logger.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001372 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301373}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001374
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375//DisableDevice disables the given device
1376//It marks the following for the given device:
1377//Device-Handler Admin-State : down
1378//Device Port-State: UNKNOWN
1379//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001380func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001381 /* On device disable ,admin state update has to be done prior sending request to agent since
1382 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001383 dh.lockDevice.Lock()
1384 dh.adminState = "down"
1385 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001386 if dh.Client != nil {
1387 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1388 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001389 dh.lockDevice.Lock()
1390 dh.adminState = "up"
1391 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001392 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001393 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001394 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001395 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001396 logger.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001397 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001398 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301399
1400 dh.discOnus = sync.Map{}
1401 dh.onus = sync.Map{}
1402
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301403 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001404 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001405 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1406 for _, port := range cloned.Ports {
1407 if port.GetType() == voltha.Port_PON_OLT {
1408 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1409 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001410 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001411 }
1412 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001413 }
1414
Girish Kumar2ad402b2020-03-20 19:45:12 +00001415 logger.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001416 return nil
1417}
1418
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301419func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001420
1421 // Update onu state as unreachable in onu adapter
1422 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301423 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001424 //get the child device for the parent device
1425 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1426 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001427 logger.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001428 }
1429 if onuDevices != nil {
1430 for _, onuDevice := range onuDevices.Items {
1431 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1432 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1433 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001434 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001435 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1436 }
1437
1438 }
1439 }
1440
1441}
1442
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001443//ReenableDevice re-enables the olt device after disable
1444//It marks the following for the given device:
1445//Device-Handler Admin-State : up
1446//Device Port-State: ACTIVE
1447//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001448func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001449 dh.lockDevice.Lock()
1450 dh.adminState = "up"
1451 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301452
1453 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1454 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301455 dh.lockDevice.Lock()
1456 dh.adminState = "down"
1457 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001458 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301459 }
1460 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001461 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001462
1463 cloned := proto.Clone(device).(*voltha.Device)
1464 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001465
kdarapu1afeceb2020-02-12 01:38:09 -05001466 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001467 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001468 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001469 //Update the device oper status as ACTIVE
1470 cloned.OperStatus = voltha.OperStatus_ACTIVE
1471 dh.device = cloned
1472
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001473 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301474 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001475 "device-id": device.Id,
1476 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001477 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001478 }
kesavand39e0aa32020-01-28 20:58:50 -05001479
Girish Kumar2ad402b2020-03-20 19:45:12 +00001480 logger.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001481
1482 return nil
1483}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001484
npujarec5762e2020-01-01 14:08:48 +05301485func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001486 var uniID uint32
1487 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301488 for _, port := range onu.UniPorts {
1489 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001490 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001491 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301492 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001493 logger.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001494 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001495 logger.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301496 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001497 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301498 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001499 }
npujarec5762e2020-01-01 14:08:48 +05301500 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001501 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301502 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001503 logger.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001504 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001505 logger.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301506 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001507 logger.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001508 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001509 logger.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301510 }
npujarec5762e2020-01-01 14:08:48 +05301511 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1512 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001513 logger.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301514 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001515 logger.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301516 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001517 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 +00001518 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001519 }
1520 return nil
1521}
1522
npujarec5762e2020-01-01 14:08:48 +05301523func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001524 nniUniID := -1
1525 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301526
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001527 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001528 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001529 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001530 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301531 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301532 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001533 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001534 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001535 logger.Debugw("NNI are ", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301536 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301537 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001538 logger.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301539 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301540 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301541 }
npujarec5762e2020-01-01 14:08:48 +05301542 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001543 }
npujarec5762e2020-01-01 14:08:48 +05301544 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001545 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301546 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001547 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001548}
1549
1550// 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 +05301551func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001552 logger.Debug("Function entry delete device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001553 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001554 if dh.adminState == "deleted" {
1555 dh.lockDevice.Unlock()
1556 return nil
1557 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001558 dh.adminState = "deleted"
1559 dh.lockDevice.Unlock()
1560 /* Clear the KV store data associated with the all the UNI ports
1561 This clears up flow data and also resource map data for various
1562 other pon resources like alloc_id and gemport_id
1563 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001564 go dh.cleanupDeviceResources(ctx)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001565 logger.Debug("Removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001566 // Stop the Stats collector
1567 dh.stopCollector <- true
1568 // stop the heartbeat check routine
1569 dh.stopHeartbeatCheck <- true
1570 //Reset the state
1571 if dh.Client != nil {
1572 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
1573 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
1574 }
1575 }
1576 cloned := proto.Clone(device).(*voltha.Device)
1577 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1578 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1579 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1580 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1581 "device-id": device.Id,
1582 "connect-status": cloned.ConnectStatus,
1583 "oper-status": cloned.OperStatus}, err).Log()
1584 }
1585 return nil
1586}
1587func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001588 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301589 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1590 var ponPort uint32
1591 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1592 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301593 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301594 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301595 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001596 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001597 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301598 }
1599 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301600 onuID := make([]uint32, 1)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001601 logger.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301602 if err = dh.clearUNIData(ctx, &onu); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001603 logger.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301604 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301605 // Clear flowids for gem cache.
1606 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301607 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301608 }
1609 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301610 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301611 }
npujarec5762e2020-01-01 14:08:48 +05301612 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301613 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301614 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301615 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001616 logger.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001617 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001618 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001619 /* Clear the flows from KV store associated with NNI port.
1620 There are mostly trap rules from NNI port (like LLDP)
1621 */
npujarec5762e2020-01-01 14:08:48 +05301622 if err := dh.clearNNIData(ctx); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001623 logger.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001624 }
A R Karthick1f85b802019-10-11 05:06:05 +00001625
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001626 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301627 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001628 }
A R Karthick1f85b802019-10-11 05:06:05 +00001629
Devmalya Paul495b94a2019-08-27 19:42:00 -04001630 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301631 dh.onus.Range(func(key interface{}, value interface{}) bool {
1632 dh.onus.Delete(key)
1633 return true
1634 })
1635
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001636 /*Delete discovered ONU map for the device*/
1637 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1638 dh.discOnus.Delete(key)
1639 return true
1640 })
1641
Devmalya Paul495b94a2019-08-27 19:42:00 -04001642 return nil
1643}
1644
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001645//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001646func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1647 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001648 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001649 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001650 logger.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001651 return nil
1652}
1653
David K. Bainbridge794735f2020-02-11 21:01:37 -08001654func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001655 logger.Debugw("Received packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001656 "packet-indication": *packetIn,
1657 "packet": hex.EncodeToString(packetIn.Pkt),
1658 })
npujarec5762e2020-01-01 14:08:48 +05301659 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001660 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001661 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001662 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001663 logger.Debugw("sending packet-in to core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001664 "logicalPortNum": logicalPortNum,
1665 "packet": hex.EncodeToString(packetIn.Pkt),
1666 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001667 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301668 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001669 "destination": "core",
1670 "source": dh.deviceType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001671 "packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001672 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001673 logger.Debugw("Success sending packet-in to core!", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001674 "packet": hex.EncodeToString(packetIn.Pkt),
1675 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001676 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001677}
1678
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001679// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301680func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001681 logger.Debugw("incoming-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001682 "deviceID": dh.deviceID,
1683 "egress_port_no": egressPortNo,
1684 "pkt-length": len(packet.Data),
1685 "packet": hex.EncodeToString(packet.Data),
1686 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001687
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001688 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001689 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001690 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1691 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301692 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1693 // Do not packet-out lldp packets on uni port.
1694 // ONOS has no clue about uni/nni ports, it just packets out on all
1695 // available ports on the Logical Switch. It should not be interested
1696 // in the UNI links.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001697 logger.Debug("dropping-lldp-packet-out-on-uni")
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301698 return nil
1699 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001700 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1701 if innerEthType == 0x8100 {
1702 // q-in-q 802.1ad or 802.1q double tagged packet.
1703 // slice out the outer tag.
1704 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001705 logger.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001706 }
1707 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001708 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1709 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001710 uniID := UniIDFromPortNum(uint32(egressPortNo))
1711
npujarec5762e2020-01-01 14:08:48 +05301712 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001713 if err != nil {
1714 // In this case the openolt agent will receive the gemPortID as 0.
1715 // The agent tries to retrieve the gemPortID in this case.
1716 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001717 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001718 "packet": hex.EncodeToString(packet.Data),
1719 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001720 }
1721
1722 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001723
Girish Kumar2ad402b2020-03-20 19:45:12 +00001724 logger.Debugw("sending-packet-to-onu", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001725 "egress_port_no": egressPortNo,
1726 "IntfId": intfID,
1727 "onuID": onuID,
1728 "uniID": uniID,
1729 "gemPortID": gemPortID,
1730 "packet": hex.EncodeToString(packet.Data),
1731 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001732
npujarec5762e2020-01-01 14:08:48 +05301733 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301734 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001735 "source": "adapter",
1736 "destination": "onu",
1737 "egress-port-number": egressPortNo,
1738 "interface-id": intfID,
1739 "oni-id": onuID,
1740 "uni-id": uniID,
1741 "gem-port-id": gemPortID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001742 "packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001743 }
1744 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001745 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1746 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001747 return olterrors.NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001748 }
1749 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001750
Girish Kumar2ad402b2020-03-20 19:45:12 +00001751 logger.Debugw("sending-packet-to-nni", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001752 "uplink_pkt": uplinkPkt,
1753 "packet": hex.EncodeToString(packet.Data),
1754 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001755
npujarec5762e2020-01-01 14:08:48 +05301756 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001757 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001758 }
1759 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001760 logger.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001761 "egress_port_no": egressPortNo,
1762 "egressPortType": egressPortType,
1763 "packet": hex.EncodeToString(packet.Data),
1764 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001765 }
1766 return nil
1767}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001768
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001769func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1770 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001771}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301772
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001773func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301774 // start the heartbeat check towards the OLT.
1775 var timerCheck *time.Timer
1776
1777 for {
1778 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1779 select {
1780 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001781 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1782 if heartBeat, err :