blob: 51c2548306ae88175bfec2f97dd3e15b6e175878 [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
cuilin20187b2a8c32019-03-26 19:52:28 -070024 "fmt"
25 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040026 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070027 "strconv"
28 "strings"
29 "sync"
30 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053031
Shrey Baid807a2a02020-04-09 12:52:45 +053032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33
Chaitrashree G Sb2b62dd2019-07-24 21:47:04 -040034 "google.golang.org/grpc/codes"
35
Matteo Scandolo945e4012019-12-12 14:16:11 -080036 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070037 "github.com/gogo/protobuf/proto"
38 "github.com/golang/protobuf/ptypes"
Esin Karamanccb714b2019-11-29 15:02:06 +000039 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
40 "github.com/opencord/voltha-lib-go/v3/pkg/log"
41 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Thomas Lee S94109f12020-03-03 16:39:29 +053042 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080043 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000044 "github.com/opencord/voltha-protos/v3/go/common"
45 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
46 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
47 oop "github.com/opencord/voltha-protos/v3/go/openolt"
48 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070049 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040050 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053051)
52
salmansiddiqui7ac62132019-08-22 03:58:50 +000053// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040054const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000055 MaxRetry = 10
56 MaxTimeOutInMs = 500
Girish Gowdracefae192020-03-19 18:14:10 -070057 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040058)
59
Girish Gowdracefae192020-03-19 18:14:10 -070060// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
61type pendingFlowRemoveDataKey struct {
62 intfID uint32
63 onuID uint32
64 uniID uint32
65}
66
67// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
68// This holds the number of pending flow removes and also a signal channel to
69// to indicate the receiver when all flow removes are handled
70type pendingFlowRemoveData struct {
71 pendingFlowRemoveCount uint32
72 allFlowsRemoved chan struct{}
73}
74
Phaneendra Manda4c62c802019-03-06 21:37:49 +053075//DeviceHandler will interact with the OLT device.
76type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070077 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070078 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040079 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070080 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053081 coreProxy adapterif.CoreProxy
82 AdapterProxy adapterif.AdapterProxy
83 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070084 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070085 exitChannel chan int
86 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053087 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070088 transitionMap *TransitionMap
89 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053090 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040091 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053092 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053093
Girish Gowdra3ab6d212020-03-24 17:33:15 -070094 discOnus sync.Map
95 onus sync.Map
96 portStats *OpenOltStatisticsMgr
97 metrics *pmmetrics.PmMetrics
98 stopCollector chan bool
99 stopHeartbeatCheck chan bool
100 activePorts sync.Map
101 stopIndications chan bool
102 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700103
104 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
105 // subscriber basis for the number of pending flow removes. This data is used
106 // to process all the flow removes for a subscriber before handling flow adds.
107 // Interleaving flow delete and flow add processing has known to cause PON resource
108 // management contentions on a per subscriber bases, so we need ensure ordering.
109 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700110}
111
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700113type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700115 deviceType string
116 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700117 onuID uint32
118 intfID uint32
119 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +0000120 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530121 losRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700122}
123
Naga Manjunath7615e552019-10-11 22:35:47 +0530124var pmNames = []string{
125 "rx_bytes",
126 "rx_packets",
127 "rx_mcast_packets",
128 "rx_bcast_packets",
129 "tx_bytes",
130 "tx_packets",
131 "tx_mcast_packets",
132 "tx_bcast_packets",
133}
134
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700135//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530136func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700137 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700138 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700139 device.deviceType = deviceTp
140 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700141 device.onuID = onuID
142 device.intfID = intfID
143 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000144 device.uniPorts = make(map[uint32]struct{})
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530145 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700146 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530147}
148
149//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530150func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700151 var dh DeviceHandler
152 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400153 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400154 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700155 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700156 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700157 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400158 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700159 dh.device = cloned
160 dh.openOLT = adapter
161 dh.exitChannel = make(chan int, 1)
162 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530163 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530164 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530165 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 -0500166 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400167 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700168 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
169
cuilin20187b2a8c32019-03-26 19:52:28 -0700170 //TODO initialize the support classes.
171 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530172}
173
174// start save the device to the data model
175func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700176 dh.lockDevice.Lock()
177 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000178 logger.Debugw("starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700179 // Add the initial device to the local model
Girish Kumar2ad402b2020-03-20 19:45:12 +0000180 logger.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530181}
182
183// stop stops the device dh. Not much to do for now
184func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700185 dh.lockDevice.Lock()
186 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000187 logger.Debug("stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700188 dh.exitChannel <- 1
Girish Kumar2ad402b2020-03-20 19:45:12 +0000189 logger.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530190}
191
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400192func macifyIP(ip net.IP) string {
193 if len(ip) > 0 {
194 oct1 := strconv.FormatInt(int64(ip[12]), 16)
195 oct2 := strconv.FormatInt(int64(ip[13]), 16)
196 oct3 := strconv.FormatInt(int64(ip[14]), 16)
197 oct4 := strconv.FormatInt(int64(ip[15]), 16)
198 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
199 }
200 return ""
201}
202
203func generateMacFromHost(host string) (string, error) {
204 var genmac string
205 var addr net.IP
206 var ips []string
207 var err error
208
Girish Kumar2ad402b2020-03-20 19:45:12 +0000209 logger.Debugw("generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400210
211 if addr = net.ParseIP(host); addr == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000212 logger.Debugw("looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400213
214 if ips, err = net.LookupHost(host); err == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000215 logger.Debugw("dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400216 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000217 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400218 }
219 genmac = macifyIP(addr)
Shrey Baid807a2a02020-04-09 12:52:45 +0530220 logger.Debugw("using-ip-as-mac",
221 log.Fields{"host": ips[0],
222 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400223 return genmac, nil
224 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000225 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400226 }
227
228 genmac = macifyIP(addr)
Shrey Baid807a2a02020-04-09 12:52:45 +0530229 logger.Debugw("using-ip-as-mac",
230 log.Fields{"host": host,
231 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400232 return genmac, nil
233}
234
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530235func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700236 slist := strings.Split(mac, ":")
237 result := make([]uint32, len(slist))
238 var err error
239 var tmp int64
240 for index, val := range slist {
241 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
242 return []uint32{1, 2, 3, 4, 5, 6}
243 }
244 result[index] = uint32(tmp)
245 }
246 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530247}
248
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700249//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 -0800250func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530251
David K. Bainbridge794735f2020-02-11 21:01:37 -0800252 switch portType {
253 case voltha.Port_ETHERNET_NNI:
254 return fmt.Sprintf("nni-%d", portNum), nil
255 case voltha.Port_PON_OLT:
256 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700257 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800258
Girish Kumarf26e4882020-03-05 06:49:10 +0000259 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530260}
261
David K. Bainbridge794735f2020-02-11 21:01:37 -0800262func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000263 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700264 if state == "up" {
265 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500266 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500267 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700268 } else {
269 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500270 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700271 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 portNum := IntfIDToPortNo(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800273 label, err := GetportLabel(portNum, portType)
274 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000275 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400276 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500277
278 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
279 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000280 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500281 }
282 if device.Ports != nil {
283 for _, dPort := range device.Ports {
284 if dPort.Type == portType && dPort.PortNo == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000285 logger.Debug("port-already-exists-updating-oper-status-of-port")
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500286 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530287 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800288 "device-id": dh.device.Id,
289 "port-type": portType,
290 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000291 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800292
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500293 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800294 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500295 }
296 }
297 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400298 // Now create Port
299 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700300 PortNo: portNum,
301 Label: label,
302 Type: portType,
303 OperStatus: operStatus,
304 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530305 logger.Debugw("sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700306 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700307 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000308 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800309 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000310 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400311 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800312 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530313}
314
315// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800316func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000317 defer logger.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700318 defer func() {
319 dh.lockDevice.Lock()
320 dh.isReadIndicationRoutineActive = false
321 dh.lockDevice.Unlock()
322 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700323 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700324 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700325 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700326 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400327 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530328 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400329 if err != nil || device == nil {
330 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000331 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400332 }
333 // When the device is in DISABLED and Adapter container restarts, we need to
334 // rebuild the locally maintained admin state.
335 if device.AdminState == voltha.AdminState_DISABLED {
336 dh.lockDevice.Lock()
337 dh.adminState = "down"
338 dh.lockDevice.Unlock()
339 }
340
David Bainbridgef5879ca2019-12-13 21:17:54 +0000341 // Create an exponential backoff around re-enabling indications. The
342 // maximum elapsed time for the back off is set to 0 so that we will
343 // continue to retry. The max interval defaults to 1m, but is set
344 // here for code clarity
345 indicationBackoff := backoff.NewExponentialBackOff()
346 indicationBackoff.MaxElapsedTime = 0
347 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700348
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700349 dh.lockDevice.Lock()
350 dh.isReadIndicationRoutineActive = true
351 dh.lockDevice.Unlock()
352
Girish Gowdra3f974912020-03-23 20:35:18 -0700353Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700354 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400355 select {
356 case <-dh.stopIndications:
Shrey Baid807a2a02020-04-09 12:52:45 +0530357 logger.Debugw("stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.deviceID})
Girish Gowdra3f974912020-03-23 20:35:18 -0700358 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400359 default:
360 indication, err := indications.Recv()
361 if err == io.EOF {
Shrey Baid807a2a02020-04-09 12:52:45 +0530362 logger.Infow("eof-for-indications",
363 log.Fields{"err": err,
364 "device-id": dh.deviceID})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400365 // Use an exponential back off to prevent getting into a tight loop
366 duration := indicationBackoff.NextBackOff()
367 if duration == backoff.Stop {
368 // If we reach a maximum then warn and reset the backoff
369 // timer and keep attempting.
Shrey Baid807a2a02020-04-09 12:52:45 +0530370 logger.Warnw("maximum-indication-backoff-reached--resetting-backoff-timer",
371 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
372 "device-id": dh.deviceID})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400373 indicationBackoff.Reset()
374 }
375 time.Sleep(indicationBackoff.NextBackOff())
Girish Gowdra3f974912020-03-23 20:35:18 -0700376 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
377 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400378 }
379 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000380 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530381 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530382 logger.Errorw("read-indication-error",
383 log.Fields{"err": err,
384 "device-id": dh.deviceID})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400385 if dh.adminState == "deleted" {
Shrey Baid807a2a02020-04-09 12:52:45 +0530386 logger.Debug("device-deleted--stopping-the-read-indication-thread")
Girish Gowdra3f974912020-03-23 20:35:18 -0700387 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400388 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700389 // Close the stream, and re-initialize it
390 if err = indications.CloseSend(); err != nil {
391 // Ok to ignore here, because we landed here due to a problem on the stream
392 // In all probability, the closeSend call may fail
Shrey Baid807a2a02020-04-09 12:52:45 +0530393 logger.Debugw("error-closing-send stream--error-ignored",
394 log.Fields{"err": err,
395 "device-id": dh.deviceID})
Girish Gowdra3f974912020-03-23 20:35:18 -0700396 }
397 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
398 return err
399 }
400 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400401 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530402 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400403 // Reset backoff if we have a successful receive
404 indicationBackoff.Reset()
405 dh.lockDevice.RLock()
406 adminState := dh.adminState
407 dh.lockDevice.RUnlock()
408 // When OLT is admin down, ignore all indications.
409 if adminState == "down" && !isIndicationAllowedDuringOltAdminDown(indication) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530410 logger.Debugw("olt-is-admin-down, ignore indication",
411 log.Fields{"indication": indication,
412 "device-id": dh.deviceID})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400413 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400414 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400415 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700416 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700417 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700418 // Close the send stream
419 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700420
Girish Gowdra3f974912020-03-23 20:35:18 -0700421 return nil
422}
423
424func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
425
426 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
427 if err != nil {
428 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
429 }
430 if indications == nil {
431 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
432 }
433
434 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400435}
436
437// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
438func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
439 switch indication.Data.(type) {
440 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
441 return true
442
443 default:
444 return false
445 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700446}
447
David K. Bainbridge794735f2020-02-11 21:01:37 -0800448func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000449 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000450 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530451 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700452 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530453 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700454 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000455 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800456 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530457 return olterrors.NewErrAdapter("failed-indication", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +0530458 "device-id": dh.deviceID,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800459 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000460 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800461 }
462 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700463}
464
David K. Bainbridge794735f2020-02-11 21:01:37 -0800465// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530466func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400467 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700468 switch indication.Data.(type) {
469 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800470 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530471 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800472 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700473 case *oop.Indication_IntfInd:
474 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800475 go func() {
476 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530477 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800478 }
479 }()
Shrey Baid807a2a02020-04-09 12:52:45 +0530480 logger.Infow("received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.deviceID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700481 case *oop.Indication_IntfOperInd:
482 intfOperInd := indication.GetIntfOperInd()
483 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800484 go func() {
485 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530486 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487 }
488 }()
npujarec5762e2020-01-01 14:08:48 +0530489 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 } else if intfOperInd.GetType() == "pon" {
491 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
492 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800493 go func() {
494 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530495 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800496 }
497 }()
kesavand39e0aa32020-01-28 20:58:50 -0500498 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700499 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530500 logger.Infow("received-interface-oper-indication",
501 log.Fields{"interfaceOperInd": intfOperInd,
502 "device-id": dh.deviceID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700503 case *oop.Indication_OnuDiscInd:
504 onuDiscInd := indication.GetOnuDiscInd()
Shrey Baid807a2a02020-04-09 12:52:45 +0530505 logger.Infow("received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.deviceID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700506 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800507 go func() {
508 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530509 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800510 }
511 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700512 case *oop.Indication_OnuInd:
513 onuInd := indication.GetOnuInd()
Shrey Baid807a2a02020-04-09 12:52:45 +0530514 logger.Infow("received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.deviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800515 go func() {
516 if err := dh.onuIndication(onuInd); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530517 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800518 }
519 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700520 case *oop.Indication_OmciInd:
521 omciInd := indication.GetOmciInd()
Shrey Baid807a2a02020-04-09 12:52:45 +0530522 logger.Debugw("received-omci-indication", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId, "device-id": dh.deviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800523 go func() {
524 if err := dh.omciIndication(omciInd); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530525 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800526 }
527 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700528 case *oop.Indication_PktInd:
529 pktInd := indication.GetPktInd()
Shrey Baid807a2a02020-04-09 12:52:45 +0530530 logger.Infow("received-packet-indication", log.Fields{"PktInd": pktInd, "device-id": dh.deviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800531 go func() {
532 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530533 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800534 }
535 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700536 case *oop.Indication_PortStats:
537 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530538 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700539 case *oop.Indication_FlowStats:
540 flowStats := indication.GetFlowStats()
Shrey Baid807a2a02020-04-09 12:52:45 +0530541 logger.Infow("received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.deviceID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700542 case *oop.Indication_AlarmInd:
543 alarmInd := indication.GetAlarmInd()
Shrey Baid807a2a02020-04-09 12:52:45 +0530544 logger.Infow("received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.deviceID})
Naga Manjunath7615e552019-10-11 22:35:47 +0530545 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700546 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530547}
548
549// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530550func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530551 //starting the stat collector
552 go startCollector(dh)
553
Girish Gowdru0c588b22019-04-23 23:24:56 -0400554 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530555 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400556 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000557 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400558 }
559 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530560}
561
562// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530563func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700564 dh.lockDevice.Lock()
565 defer dh.lockDevice.Unlock()
Shrey Baid807a2a02020-04-09 12:52:45 +0530566 logger.Debugw("do-state-down-start", log.Fields{"device-id": dh.deviceID})
Girish Gowdrud4245152019-05-10 00:47:31 -0400567
npujarec5762e2020-01-01 14:08:48 +0530568 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400569 if err != nil || device == nil {
570 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000571 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400572 }
573
574 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400575
576 //Update the device oper state and connection status
577 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400578 dh.device = cloned
579
David K. Bainbridge794735f2020-02-11 21:01:37 -0800580 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000581 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400582 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400583
584 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530585 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400586 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000587 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400588 }
589 for _, onuDevice := range onuDevices.Items {
590
591 // Update onu state as down in onu adapter
592 onuInd := oop.OnuIndication{}
593 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800594 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700595 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800596 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530597 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800598 "source": "openolt",
599 "onu-indicator": onuInd,
600 "device-type": onuDevice.Type,
601 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700602 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700603 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400604 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700605 /* Discovered ONUs entries need to be cleared , since after OLT
606 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530607 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000608 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700609 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530610}
611
612// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530613func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400614 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800615 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530616 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800617 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000618 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400619 }
620 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530621}
622
623// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530624func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400625 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530626 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400627 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530628}
629
630// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530631func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530632 logger.Debugw("olt-device-connected", log.Fields{"device-id": dh.deviceID})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400633
634 // Case where OLT is disabled and then rebooted.
635 if dh.adminState == "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000636 logger.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530637 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400638 if err != nil || device == nil {
639 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530640 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400641 }
642
643 cloned := proto.Clone(device).(*voltha.Device)
644 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
645 cloned.OperStatus = voltha.OperStatus_UNKNOWN
646 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530647 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530648 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400649 }
650
Chaitrashree G S44124192019-08-07 20:21:36 -0400651 // 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 +0530652 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400653 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530654 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400655 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400656 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
657 // all the modules initialized and ready to handle incoming ONUs.
658
659 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
660 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
661 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400662
663 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800664 go func() {
665 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530666 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800667 }
668 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400669 return nil
670 }
671
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700672 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400673 if err != nil || device == nil {
674 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000675 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400676 }
kesavand39e0aa32020-01-28 20:58:50 -0500677 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500678 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000679 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400680 }
681
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400682 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
683 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400684 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530685
cuilin20187b2a8c32019-03-26 19:52:28 -0700686 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800687 go func() {
688 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530689 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800690 }
691 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700692 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530693}
694
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400695func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
696 deviceInfo, err := dh.populateDeviceInfo()
697
698 if err != nil {
699 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
700 }
701 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
702 // Instantiate resource manager
703 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
704 return olterrors.ErrResourceManagerInstantiating
705 }
706
707 // Instantiate flow manager
708 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
709 return olterrors.ErrResourceManagerInstantiating
710
711 }
712 /* TODO: Instantiate Alarm , stats , BW managers */
713 /* Instantiating Event Manager to handle Alarms and KPIs */
714 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
715
716 // Stats config for new device
717 dh.portStats = NewOpenOltStatsMgr(dh)
718
719 return nil
720
721}
722
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400723func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
724 var err error
725 var deviceInfo *oop.DeviceInfo
726
727 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
728
729 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000730 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400731 }
732 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000733 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400734 }
735
Shrey Baid807a2a02020-04-09 12:52:45 +0530736 logger.Debugw("fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.deviceID})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400737 dh.device.Root = true
738 dh.device.Vendor = deviceInfo.Vendor
739 dh.device.Model = deviceInfo.Model
740 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
741 dh.device.HardwareVersion = deviceInfo.HardwareVersion
742 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
743
744 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000745 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400746 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
747 genmac, err := generateMacFromHost(host)
748 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000749 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400750 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000751 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400752 dh.device.MacAddress = genmac
753 } else {
754 dh.device.MacAddress = deviceInfo.DeviceId
755 }
756
757 // Synchronous call to update device - this method is run in its own go routine
758 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000759 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400760 }
761
762 return deviceInfo, nil
763}
764
Naga Manjunath7615e552019-10-11 22:35:47 +0530765func startCollector(dh *DeviceHandler) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530766 logger.Debugf("starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530767 context := make(map[string]string)
768 for {
769 select {
770 case <-dh.stopCollector:
Shrey Baid807a2a02020-04-09 12:52:45 +0530771 logger.Debugw("stopping-collector-for-olt", log.Fields{"deviceID:": dh.deviceID})
Naga Manjunath7615e552019-10-11 22:35:47 +0530772 return
773 default:
774 freq := dh.metrics.ToPmConfigs().DefaultFreq
775 time.Sleep(time.Duration(freq) * time.Second)
776 context["oltid"] = dh.deviceID
777 context["devicetype"] = dh.deviceType
778 // NNI Stats
779 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
Girish Kumar2ad402b2020-03-20 19:45:12 +0000780 logger.Debugf("Collect-NNI-Metrics %v", cmnni)
Naga Manjunath7615e552019-10-11 22:35:47 +0530781 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
Shrey Baid807a2a02020-04-09 12:52:45 +0530782 logger.Debugf("publish-nni-metrics")
Naga Manjunath7615e552019-10-11 22:35:47 +0530783 // PON Stats
784 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500785 for i := uint32(0); i < NumPonPORTS; i++ {
786 if val, ok := dh.activePorts.Load(i); ok && val == true {
787 cmpon := dh.portStats.collectPONMetrics(i)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000788 logger.Debugf("Collect-PON-Metrics %v", cmpon)
Chaitrashree G Sef088112020-02-03 21:39:27 -0500789 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
Shrey Baid807a2a02020-04-09 12:52:45 +0530790 logger.Debugf("publish-pon-metrics")
Chaitrashree G Sef088112020-02-03 21:39:27 -0500791 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530792 }
793 }
794 }
795}
796
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700797//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530798func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400799 dh.transitionMap = NewTransitionMap(dh)
Shrey Baid807a2a02020-04-09 12:52:45 +0530800 logger.Infow("adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530801 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530802
803 // Now, set the initial PM configuration for that device
804 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530805 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530806 }
807
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400808 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530809}
810
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700811//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530812func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700813 return &ic.SwitchCapability{
814 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530815 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700816 HwDesc: "open_pon",
817 SwDesc: "open_pon",
818 SerialNum: dh.device.SerialNumber,
819 },
820 SwitchFeatures: &of.OfpSwitchFeatures{
821 NBuffers: 256,
822 NTables: 2,
823 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
824 of.OfpCapabilities_OFPC_TABLE_STATS |
825 of.OfpCapabilities_OFPC_PORT_STATS |
826 of.OfpCapabilities_OFPC_GROUP_STATS),
827 },
828 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530829}
830
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700831//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530832func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700833 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700834 return &ic.PortCapability{
835 Port: &voltha.LogicalPort{
836 OfpPort: &of.OfpPort{
837 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
838 Config: 0,
839 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700840 Curr: capacity,
841 Advertised: capacity,
842 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700843 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
844 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
845 },
846 DeviceId: dh.device.Id,
847 DevicePortNo: uint32(portNo),
848 },
849 }, nil
850}
851
David K. Bainbridge794735f2020-02-11 21:01:37 -0800852func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530853 logger.Debugw("omci-indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.deviceID})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700854 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700855 var deviceID string
856 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700857
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400858 transid := extractOmciTransactionID(omciInd.Pkt)
Shrey Baid807a2a02020-04-09 12:52:45 +0530859 logger.Debugw("recv-omci-msg", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.deviceID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400860 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
861
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700862 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530863
864 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
865
Shrey Baid807a2a02020-04-09 12:52:45 +0530866 logger.Debugw("omci-indication-for-a-device-not-in-cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.deviceID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700867 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700868 kwargs := make(map[string]interface{})
869 kwargs["onu_id"] = omciInd.OnuId
870 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700871
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700872 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
873 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530874 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800875 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000876 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700877 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700878 deviceType = onuDevice.Type
879 deviceID = onuDevice.Id
880 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
881 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530882 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700883 } else {
884 //found in cache
Shrey Baid807a2a02020-04-09 12:52:45 +0530885 logger.Debugw("omci-indication-for-a-device-in-cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.deviceID})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530886 deviceType = onuInCache.(*OnuDevice).deviceType
887 deviceID = onuInCache.(*OnuDevice).deviceID
888 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700889 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700890
891 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800892 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700893 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800894 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530895 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800896 "source": dh.deviceType,
897 "destination": deviceType,
898 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000899 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700900 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800901 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530902}
903
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700904//ProcessInterAdapterMessage sends the proxied messages to the target device
905// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
906// is meant, and then send the unmarshalled omci message to this onu
907func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530908 logger.Debugw("process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700909 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700910 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700911 fromTopic := msg.Header.FromTopic
912 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700913 toDeviceID := msg.Header.ToDeviceId
914 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700915
Shrey Baid807a2a02020-04-09 12:52:45 +0530916 logger.Debugw("omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700917
918 msgBody := msg.GetBody()
919
920 omciMsg := &ic.InterAdapterOmciMessage{}
921 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000922 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700923 }
924
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700925 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700926 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
927 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530928 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800929 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000930 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700931 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530932 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 -0800933 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530934 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800935 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000936 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800937 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700938 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +0530939 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 -0800940 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530941 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800942 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000943 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800944 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700945 }
946
947 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000948 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700949 }
950 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530951}
952
David K. Bainbridge794735f2020-02-11 21:01:37 -0800953func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700954 var intfID uint32
955 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000956 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700957 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700958 intfID = onuDevice.ProxyAddress.GetChannelId()
959 onuID = onuDevice.ProxyAddress.GetOnuId()
960 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700961 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700962 intfID = omciMsg.GetProxyAddress().GetChannelId()
963 onuID = omciMsg.GetProxyAddress().GetOnuId()
964 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700965 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700966 if connectStatus != voltha.ConnectStatus_REACHABLE {
Shrey Baid807a2a02020-04-09 12:52:45 +0530967 logger.Debugw("onu-not-reachable--cannot-send-omci", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800968
Thomas Lee S94109f12020-03-03 16:39:29 +0530969 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800970 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000971 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700972 }
973
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400974 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
975 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700976 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400977 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
978 hex.Encode(hexPkt, omciMsg.Message)
979 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
980
981 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
982 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
983 transid := extractOmciTransactionID(omciMsg.Message)
984 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
985 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700986
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700987 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
988 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530989 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800990 "interface-id": intfID,
991 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000992 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700993 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800994 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700995}
996
David K. Bainbridge794735f2020-02-11 21:01:37 -0800997func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530998 logger.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.deviceID})
Andrea Campanellab83b39d2020-03-30 11:41:16 +0200999 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
1000 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
1001 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001002 // TODO: need resource manager
1003 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001004 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301005 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001006 st, _ := status.FromError(err)
1007 if st.Code() == codes.AlreadyExists {
Shrey Baid807a2a02020-04-09 12:52:45 +05301008 logger.Debugw("onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onuID": onuID, "device-id": dh.deviceID})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001009 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301010 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.deviceID}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001011 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001012 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301013 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.deviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -07001014 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001015 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001016}
1017
David K. Bainbridge794735f2020-02-11 21:01:37 -08001018func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001019
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001020 channelID := onuDiscInd.GetIntfId()
1021 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001022
Girish Kumar2ad402b2020-03-20 19:45:12 +00001023 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301024
cuilin20187b2a8c32019-03-26 19:52:28 -07001025 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001026 if sn != "" {
1027 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001028 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001029 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001030 }
1031
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301032 var alarmInd oop.OnuAlarmIndication
1033 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001034 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301035
1036 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1037 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1038 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1039 OnuLosRaise event sent for it */
1040 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1041 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1042 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Shrey Baid807a2a02020-04-09 12:52:45 +05301043 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301044 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1045 "currentIntfId": onuDiscInd.GetIntfId()})
1046 // TODO:: Should we need to ignore raising OnuLosClear event
1047 // when onu connected to different PON?
1048 }
1049 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1050 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1051 alarmInd.LosStatus = statusCheckOff
1052 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1053 }
1054 return true
1055 })
1056
Girish Kumar2ad402b2020-03-20 19:45:12 +00001057 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001058 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001059 }
1060
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001061 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001062
1063 // check the ONU is already know to the OLT
1064 // NOTE the second time the ONU is discovered this should return a device
1065 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1066
1067 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001068 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 -08001069 if e, ok := status.FromError(err); ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001070 logger.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001071 switch e.Code() {
1072 case codes.Internal:
1073 // this probably means NOT FOUND, so just create a new device
1074 onuDevice = nil
1075 case codes.DeadlineExceeded:
1076 // if the call times out, cleanup and exit
1077 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001078 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001079 }
1080 }
1081 }
1082
1083 if onuDevice == nil {
1084 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Girish Kumar2ad402b2020-03-20 19:45:12 +00001085 logger.Infow("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001086 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001087 ponintfid := onuDiscInd.GetIntfId()
1088 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301089 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001090 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001091
Girish Kumar2ad402b2020-03-20 19:45:12 +00001092 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001093
1094 if err != nil {
1095 // if we can't create an ID in resource manager,
1096 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001097 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001098 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001099 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001100 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001101 }
1102
1103 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1104 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001105 dh.discOnus.Delete(sn)
1106 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 +05301107 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001109 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001110 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001111 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Shrey Baid807a2a02020-04-09 12:52:45 +05301112 logger.Infow("onu-child-device-added",
1113 log.Fields{"onuDevice": onuDevice,
1114 "sn": sn,
1115 "onuID": onuID,
1116 "device-id": dh.deviceID})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001117 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001118
1119 // we can now use the existing ONU Id
1120 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001121 //Insert the ONU into cache to use in OnuIndication.
1122 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Shrey Baid807a2a02020-04-09 12:52:45 +05301123 logger.Debugw("onu-discovery-indication-key-create",
1124 log.Fields{"onuID": onuID,
1125 "intfId": onuDiscInd.GetIntfId(),
1126 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001127 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001128
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301129 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301130 dh.onus.Store(onuKey, onuDev)
Shrey Baid807a2a02020-04-09 12:52:45 +05301131 logger.Debugw("new-onu-device-discovered",
1132 log.Fields{"onu": onuDev,
1133 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001134
David K. Bainbridge794735f2020-02-11 21:01:37 -08001135 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301136 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001137 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001138 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001139 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301140 logger.Infow("onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001141 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301142 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001143 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001144 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001145 }
1146 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001147}
1148
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001150 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1151
1152 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001153 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001154 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001155 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001156 foundInCache := false
Shrey Baid807a2a02020-04-09 12:52:45 +05301157 logger.Debugw("onu-indication-key-create",
1158 log.Fields{"onuId": onuInd.OnuId,
1159 "intfId": onuInd.GetIntfId(),
1160 "device-id": dh.deviceID})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001161 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301162
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 errFields := log.Fields{"device-id": dh.device.Id}
1164
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301165 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1166
Mahir Gunyele77977b2019-06-27 05:36:22 -07001167 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1168 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001169 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1170 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001171 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001172 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1173 if serialNumber != "" {
1174 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001175 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001176 } else {
1177 kwargs["onu_id"] = onuInd.OnuId
1178 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001179 errFields["onu-id"] = onuInd.OnuId
1180 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001181 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001182 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001183 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001184
David K. Bainbridge794735f2020-02-11 21:01:37 -08001185 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001186 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001187 }
1188
David K. Bainbridge794735f2020-02-11 21:01:37 -08001189 if onuDevice.ParentPortNo != ponPort {
Shrey Baid807a2a02020-04-09 12:52:45 +05301190 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 "previousIntfId": onuDevice.ParentPortNo,
1192 "currentIntfId": ponPort})
1193 }
1194
1195 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Shrey Baid807a2a02020-04-09 12:52:45 +05301196 logger.Warnw("onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
1197 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1198 "received-onu-id": onuInd.OnuId,
1199 "device-id": dh.deviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 }
1201 if !foundInCache {
1202 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1203
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301204 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 -08001205
1206 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001207 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001208 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001209 }
1210 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001211}
1212
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001213func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301214 ctx := context.TODO()
Shrey Baid807a2a02020-04-09 12:52:45 +05301215 logger.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001216 if onuInd.AdminState == "down" {
1217 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1218 if onuInd.OperState != "down" {
Shrey Baid807a2a02020-04-09 12:52:45 +05301219 logger.Warnw("onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001220 onuInd.OperState = "down"
1221 }
1222 }
1223
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224 switch onuInd.OperState {
1225 case "down":
Shrey Baid807a2a02020-04-09 12:52:45 +05301226 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001227 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301228 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001229 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1230 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301231 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001232 "onu-indicator": onuInd,
1233 "source": "openolt",
1234 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001235 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001236 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001237 case "up":
Shrey Baid807a2a02020-04-09 12:52:45 +05301238 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Matt Jeanneret53539512019-07-20 14:47:02 -04001239 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301240 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001241 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1242 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301243 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 "onu-indicator": onuInd,
1245 "source": "openolt",
1246 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001247 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001248 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001249 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001250 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001251 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001253}
1254
cuilin20187b2a8c32019-03-26 19:52:28 -07001255func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1256 if serialNum != nil {
1257 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001258 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001259 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001260}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001261func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1262 decodedStr, err := hex.DecodeString(serialNum[4:])
1263 if err != nil {
1264 return nil, err
1265 }
1266 return &oop.SerialNumber{
1267 VendorId: []byte(serialNum[:4]),
1268 VendorSpecific: []byte(decodedStr),
1269 }, nil
1270}
cuilin20187b2a8c32019-03-26 19:52:28 -07001271
1272func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1273 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001274 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001275 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1276 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1277 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1278 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1279 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1280 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1281 return tmp
1282}
1283
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001284//UpdateFlowsBulk upates the bulk flow
1285func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301286 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001287}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001288
1289//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001290func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301291 logger.Debugw("getchilddevice",
1292 log.Fields{"pon-port": parentPort,
1293 "onuID": onuID,
1294 "device-id": dh.deviceID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001295 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001296 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001297 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001298 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001299 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001300 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001301 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001302 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001303 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301304 logger.Debugw("successfully-received-child-device-from-core", log.Fields{"child-device-id": onuDevice.Id, "child-device-sn": onuDevice.SerialNumber})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001305 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301306}
1307
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001308// SendPacketInToCore sends packet-in to core
1309// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1310// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001311func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001312 logger.Debugw("send-packet-in-to-core", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301313 "port": logicalPort,
1314 "packet": hex.EncodeToString(packetPayload),
1315 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001316 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301318 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001319 "source": "adapter",
1320 "destination": "core",
1321 "device-id": dh.device.Id,
1322 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001323 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001324 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301325 logger.Debugw("sent-packet-in-to-core-successfully", log.Fields{
1326 "packet": hex.EncodeToString(packetPayload),
1327 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001328 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001329 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001330}
1331
A R Karthick1f85b802019-10-11 05:06:05 +00001332// AddUniPortToOnu adds the uni port to the onu device
1333func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1334 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301335
1336 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001337 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301338 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1339 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001340 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001341 }
1342 }
1343}
1344
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301346func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301347 logger.Debugw("received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001348
1349 var errorsList []error
1350
Girish Gowdru0c588b22019-04-23 23:24:56 -04001351 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001352 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001353 dh.incrementActiveFlowRemoveCount(flow)
1354
Shrey Baid807a2a02020-04-09 12:52:45 +05301355 logger.Debugw("removing-flow",
1356 log.Fields{"device-id": device.Id,
1357 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001358 err := dh.flowMgr.RemoveFlow(ctx, flow)
1359 if err != nil {
1360 errorsList = append(errorsList, err)
1361 }
1362
1363 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001364 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301365
1366 for _, flow := range flows.ToAdd.Items {
Shrey Baid807a2a02020-04-09 12:52:45 +05301367 logger.Debugw("adding-flow",
1368 log.Fields{"device-id": device.Id,
1369 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001370 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1371 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001372 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1373 if err != nil {
1374 errorsList = append(errorsList, err)
1375 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301376 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001377 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001378
Girish Gowdracefae192020-03-19 18:14:10 -07001379 // 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 +00001380 if groups != nil {
1381 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001382 err := dh.flowMgr.AddGroup(ctx, group)
1383 if err != nil {
1384 errorsList = append(errorsList, err)
1385 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001386 }
1387 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001388 err := dh.flowMgr.ModifyGroup(ctx, group)
1389 if err != nil {
1390 errorsList = append(errorsList, err)
1391 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001392 }
1393 if len(groups.ToRemove.Items) != 0 {
Shrey Baid807a2a02020-04-09 12:52:45 +05301394 logger.Debugw("group-delete-operation-not-supported", log.Fields{"device-id": dh.deviceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00001395 }
1396 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001397 if len(errorsList) > 0 {
1398 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1399 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301400 logger.Debugw("updated-flows-incrementally-successfully", log.Fields{"device-id": dh.deviceID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001401 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301402}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001403
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001404//DisableDevice disables the given device
1405//It marks the following for the given device:
1406//Device-Handler Admin-State : down
1407//Device Port-State: UNKNOWN
1408//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001409func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001410 /* On device disable ,admin state update has to be done prior sending request to agent since
1411 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001412 dh.lockDevice.Lock()
1413 dh.adminState = "down"
1414 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001415 if dh.Client != nil {
1416 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1417 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001418 dh.lockDevice.Lock()
1419 dh.adminState = "up"
1420 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001421 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001422 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001423 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001424 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301425 logger.Debugw("olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001426 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001427 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301428
1429 dh.discOnus = sync.Map{}
1430 dh.onus = sync.Map{}
1431
Thomas Lee S85f37312020-04-03 17:06:12 +05301432 //stopping the stats collector
1433 dh.stopCollector <- true
1434
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301435 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001436 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001437 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1438 for _, port := range cloned.Ports {
1439 if port.GetType() == voltha.Port_PON_OLT {
1440 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1441 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001442 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001443 }
1444 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001445 }
1446
Shrey Baid807a2a02020-04-09 12:52:45 +05301447 logger.Debugw("disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001448 return nil
1449}
1450
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301451func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001452
1453 // Update onu state as unreachable in onu adapter
1454 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301455 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001456 //get the child device for the parent device
1457 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1458 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301459 logger.Errorw("failed-to-get-child-devices-information", log.Fields{"device-id": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001460 }
1461 if onuDevices != nil {
1462 for _, onuDevice := range onuDevices.Items {
1463 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1464 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1465 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001466 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301467 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001468 }
1469
1470 }
1471 }
1472
1473}
1474
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001475//ReenableDevice re-enables the olt device after disable
1476//It marks the following for the given device:
1477//Device-Handler Admin-State : up
1478//Device Port-State: ACTIVE
1479//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001480func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001481 dh.lockDevice.Lock()
1482 dh.adminState = "up"
1483 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301484
1485 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1486 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301487 dh.lockDevice.Lock()
1488 dh.adminState = "down"
1489 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001490 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301491 }
1492 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001493 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001494
1495 cloned := proto.Clone(device).(*voltha.Device)
1496 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001497
kdarapu1afeceb2020-02-12 01:38:09 -05001498 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001499 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001500 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001501 //Update the device oper status as ACTIVE
1502 cloned.OperStatus = voltha.OperStatus_ACTIVE
1503 dh.device = cloned
1504
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001505 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301506 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001507 "device-id": device.Id,
1508 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001509 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001510 }
kesavand39e0aa32020-01-28 20:58:50 -05001511
Shrey Baid807a2a02020-04-09 12:52:45 +05301512 logger.Debugw("reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001513
1514 return nil
1515}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001516
npujarec5762e2020-01-01 14:08:48 +05301517func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001518 var uniID uint32
1519 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301520 for _, port := range onu.UniPorts {
1521 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001522 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001523 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301524 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301525 logger.Debugw("failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001526 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301527 logger.Debugw("deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301528 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001529 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301530 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001531 }
npujarec5762e2020-01-01 14:08:48 +05301532 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001533 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301534 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301535 logger.Debugw("failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001536 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301537 logger.Debugw("removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301538 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301539 logger.Debugw("failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001540 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301541 logger.Debugw("removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301542 }
npujarec5762e2020-01-01 14:08:48 +05301543 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1544 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301545 logger.Debugw("failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301546 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301547 logger.Debugw("removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301548 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301549 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 +00001550 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001551 }
1552 return nil
1553}
1554
npujarec5762e2020-01-01 14:08:48 +05301555func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001556 nniUniID := -1
1557 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301558
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001559 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001560 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001561 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001562 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301563 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301564 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001565 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001566 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301567 logger.Debugw("nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301568 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301569 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Shrey Baid807a2a02020-04-09 12:52:45 +05301570 logger.Debugw("current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301571 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301572 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301573 }
npujarec5762e2020-01-01 14:08:48 +05301574 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001575 }
npujarec5762e2020-01-01 14:08:48 +05301576 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001577 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301578 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001579 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001580}
1581
1582// 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 +05301583func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301584 logger.Debug("function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001585 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001586 if dh.adminState == "deleted" {
1587 dh.lockDevice.Unlock()
1588 return nil
1589 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001590 dh.adminState = "deleted"
1591 dh.lockDevice.Unlock()
1592 /* Clear the KV store data associated with the all the UNI ports
1593 This clears up flow data and also resource map data for various
1594 other pon resources like alloc_id and gemport_id
1595 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001596 go dh.cleanupDeviceResources(ctx)
Shrey Baid807a2a02020-04-09 12:52:45 +05301597 logger.Debug("removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001598 // Stop the Stats collector
1599 dh.stopCollector <- true
1600 // stop the heartbeat check routine
1601 dh.stopHeartbeatCheck <- true
1602 //Reset the state
1603 if dh.Client != nil {
1604 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
1605 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
1606 }
1607 }
1608 cloned := proto.Clone(device).(*voltha.Device)
1609 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1610 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1611 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1612 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1613 "device-id": device.Id,
1614 "connect-status": cloned.ConnectStatus,
1615 "oper-status": cloned.OperStatus}, err).Log()
1616 }
1617 return nil
1618}
1619func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001620 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301621 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1622 var ponPort uint32
1623 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1624 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301625 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301626 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301627 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001628 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001629 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301630 }
1631 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301632 onuID := make([]uint32, 1)
Shrey Baid807a2a02020-04-09 12:52:45 +05301633 logger.Debugw("onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301634 if err = dh.clearUNIData(ctx, &onu); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301635 logger.Errorw("failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301636 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301637 // Clear flowids for gem cache.
1638 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301639 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301640 }
1641 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301642 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301643 }
npujarec5762e2020-01-01 14:08:48 +05301644 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301645 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301646 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301647 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301648 logger.Errorw("failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001649 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001650 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001651 /* Clear the flows from KV store associated with NNI port.
1652 There are mostly trap rules from NNI port (like LLDP)
1653 */
npujarec5762e2020-01-01 14:08:48 +05301654 if err := dh.clearNNIData(ctx); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301655 logger.Errorw("failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001656 }
A R Karthick1f85b802019-10-11 05:06:05 +00001657
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001658 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301659 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001660 }
A R Karthick1f85b802019-10-11 05:06:05 +00001661
Devmalya Paul495b94a2019-08-27 19:42:00 -04001662 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301663 dh.onus.Range(func(key interface{}, value interface{}) bool {
1664 dh.onus.Delete(key)
1665 return true
1666 })
1667
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001668 /*Delete discovered ONU map for the device*/
1669 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1670 dh.discOnus.Delete(key)
1671 return true
1672 })
1673
Devmalya Paul495b94a2019-08-27 19:42:00 -04001674 return nil
1675}
1676
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001677//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001678func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1679 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001680 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001681 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301682 logger.Debugw("rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001683 return nil
1684}
1685
David K. Bainbridge794735f2020-02-11 21:01:37 -08001686func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301687 logger.Debugw("received-packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001688 "packet-indication": *packetIn,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001689 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001690 "packet": hex.EncodeToString(packetIn.Pkt),
1691 })
npujarec5762e2020-01-01 14:08:48 +05301692 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001693 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001694 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001695 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301696 logger.Debugw("sending-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001697 "logicalPortNum": logicalPortNum,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001698 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001699 "packet": hex.EncodeToString(packetIn.Pkt),
1700 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001701 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301702 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001703 "destination": "core",
1704 "source": dh.deviceType,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001705 "device-id": dh.device.Id,
1706 "packet": hex.EncodeToString(packetIn.Pkt),
1707 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001708 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301709 logger.Debugw("success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001710 "packet": hex.EncodeToString(packetIn.Pkt),
Shrey Baid807a2a02020-04-09 12:52:45 +05301711 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001712 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001713 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001714}
1715
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001716// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301717func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001718 logger.Debugw("incoming-packet-out", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301719 "device-id": dh.deviceID,
1720 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001721 "pkt-length": len(packet.Data),
1722 "packet": hex.EncodeToString(packet.Data),
1723 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001724
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001725 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001726 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001727 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1728 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301729 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1730 // Do not packet-out lldp packets on uni port.
1731 // ONOS has no clue about uni/nni ports, it just packets out on all
1732 // available ports on the Logical Switch. It should not be interested
1733 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001734 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1735 "device-id": dh.device.Id,
1736 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301737 return nil
1738 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001739 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1740 if innerEthType == 0x8100 {
1741 // q-in-q 802.1ad or 802.1q double tagged packet.
1742 // slice out the outer tag.
1743 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001744 logger.Debugw("packet-now-single-tagged", log.Fields{
1745 "packetData": hex.EncodeToString(packet.Data),
1746 "device-id": dh.device.Id,
1747 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001748 }
1749 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001750 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1751 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001752 uniID := UniIDFromPortNum(uint32(egressPortNo))
1753
npujarec5762e2020-01-01 14:08:48 +05301754 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001755 if err != nil {
1756 // In this case the openolt agent will receive the gemPortID as 0.
1757 // The agent tries to retrieve the gemPortID in this case.
1758 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001759 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001760 "packet": hex.EncodeToString(packet.Data),
Shrey Baid807a2a02020-04-09 12:52:45 +05301761 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001762 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001763 }
1764
1765 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001766
Girish Kumar2ad402b2020-03-20 19:45:12 +00001767 logger.Debugw("sending-packet-to-onu", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301768 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001769 "IntfId": intfID,
1770 "onuID": onuID,
1771 "uniID": uniID,
1772 "gemPortID": gemPortID,
1773 "packet": hex.EncodeToString(packet.Data),
Shrey Baid807a2a02020-04-09 12:52:45 +05301774 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001775 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001776
npujarec5762e2020-01-01 14:08:48 +05301777 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301778 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001779 "source": "adapter",
1780 "destination": "onu",
1781 "egress-port-number": egressPortNo,
1782 "interface-id": intfID,
1783 "oni-id": onuID,
1784 "uni-id": uniID,
1785 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001786 "packet": hex.EncodeToString(packet.Data),
1787 "device-id": dh.device.Id,
1788 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001789 }
1790 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001791 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1792 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001793 return olterrors.NewErrInvalidValue(log.Fields{
1794 "egress-nni-port": egressPortNo,
1795 "device-id": dh.device.Id,
1796 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001797 }
1798 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001799
Girish Kumar2ad402b2020-03-20 19:45:12 +00001800 logger.Debugw("sending-packet-to-nni", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301801 "uplink-pkt": uplinkPkt,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001802 "packet": hex.EncodeToString(packet.Data),
Shrey Baid807a2a02020-04-09 12:52:45 +05301803 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001804 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001805
npujarec5762e2020-01-01 14:08:48 +05301806 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001807 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1808 "packet": hex.EncodeToString(packet.Data),
1809 "device-id": dh.device.Id,
1810 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001811 }
1812 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301813 logger.Warnw("packet-out-to-this-interface-type-not-implemented", log.Fields{
1814 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001815 "egressPortType": egressPortType,
1816 "packet": hex.EncodeToString(packet.Data),
Shrey Baid807a2a02020-04-09 12:52:45 +05301817 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001818 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001819 }
1820 return nil
1821}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001822
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001823func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1824 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001825}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301826
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001827func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301828 // start the heartbeat check towards the OLT.
1829 var timerCheck *time.Timer
1830
1831 for {
1832 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1833 select {
1834 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001835 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1836 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301837 logger.Warnw("hearbeat-failed", log.Fields{"device-id": dh.deviceID})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301838 if timerCheck == nil {
1839 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001840 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301841 }
1842 } else {
1843 if timerCheck != nil {
1844 if timerCheck.Stop() {
Shrey Baid807a2a02020-04-09 12:52:45 +05301845 logger.Debugw("got-hearbeat-within-timeout", log.Fields{"device-id": dh.deviceID})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301846 }
1847 timerCheck = nil
1848 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301849 logger.Debugw("hearbeat",
1850 log.Fields{"signature": heartBeat,
1851 "device-id": dh.deviceID})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301852 }
1853 cancel()
1854 case <-dh.stopHeartbeatCheck:
Shrey Baid807a2a02020-04-09 12:52:45 +05301855 logger.Debugw("stopping-heart-beat-check", log.Fields{"device-id": dh.deviceID})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301856 return
1857 }
1858 }
1859}
1860
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001861func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1862 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1863 if err != nil || device == nil {
1864 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1865 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301866
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001867 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1868 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1869 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1870 }
1871 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1872 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1873 }
1874 go dh.cleanupDeviceResources(ctx)
1875
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001876 dh.lockDevice.RLock()
1877 // Stop the read indication only if it the routine is active
1878 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1879 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1880 // on next execution of the readIndication routine.
1881 if dh.isReadIndicationRoutineActive {
1882 dh.stopIndications <- true
1883 }
1884 dh.lockDevice.RUnlock()
1885
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001886 dh.transitionMap.Handle(ctx, DeviceInit)
1887
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301888 }
1889}
kesavand39e0aa32020-01-28 20:58:50 -05001890
1891// EnablePort to enable Pon interface
1892func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001893 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001894 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001895}
1896
1897// DisablePort to disable pon interface
1898func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001899 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001900 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001901}
1902
kdarapu1afeceb2020-02-12 01:38:09 -05001903//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1904func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301905 ctx := context.Background()
Shrey Baid807a2a02020-04-09 12:52:45 +05301906 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.deviceID})
kesavand39e0aa32020-01-28 20:58:50 -05001907 if port.GetType() == voltha.Port_ETHERNET_NNI {
1908 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001909 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301910 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301911 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001912 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001913 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001914 }
1915 // fetch interfaceid from PortNo
1916 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1917 ponIntf := &oop.Interface{IntfId: ponID}
1918 var operStatus voltha.OperStatus_Types
1919 if enablePort {
1920 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301921 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001922
1923 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301924 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001925 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001926 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001927 }
1928 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001929 dh.activePorts.Store(ponID, true)
Shrey Baid807a2a02020-04-09 12:52:45 +05301930 logger.Infow("enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001931 } else {
1932 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301933 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001934 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301935 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001936 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001937 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001938 }
1939 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001940 dh.activePorts.Store(ponID, false)
Shrey Baid807a2a02020-04-09 12:52:45 +05301941 logger.Infow("disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001942 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001943 if err := dh.coreProxy.PortStateUpdate(ctx, dh.deviceID, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301944 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001945 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001946 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001947 }
1948 return nil
1949}
1950
kdarapu1afeceb2020-02-12 01:38:09 -05001951//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1952func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001953 cloned := proto.Clone(device).(*voltha.Device)
1954 // Disable the port and update the oper_port_status to core
1955 // if the Admin state of the port is disabled on reboot and re-enable device.
1956 for _, port := range cloned.Ports {
1957 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001958 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301959 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001960 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001961 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001962 }
1963 }
1964 }
1965 return nil
1966}
1967
1968//populateActivePorts to populate activePorts map
1969func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301970 logger.Infow("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001971 for _, port := range device.Ports {
1972 if port.Type == voltha.Port_ETHERNET_NNI {
1973 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001974 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001975 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001976 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001977 }
1978 }
1979 if port.Type == voltha.Port_PON_OLT {
1980 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001981 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001982 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001983 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001984 }
1985 }
1986 }
1987}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001988
1989// ChildDeviceLost deletes ONU and clears pon resources related to it.
1990func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001991 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001992 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1993 onuKey := dh.formOnuKey(IntfID, onuID)
1994 onuDevice, ok := dh.onus.Load(onuKey)
1995 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301996 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001997 log.Fields{
1998 "device-id": dh.deviceID,
1999 "onu-id": onuID,
2000 "interface-id": IntfID}, nil).Log()
2001 }
2002 var sn *oop.SerialNumber
2003 var err error
2004 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302005 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002006 log.Fields{
2007 "devicer-id": dh.deviceID,
2008 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2009 }
2010 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
2011 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302012 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002013 "device-id": dh.deviceID,
2014 "onu-id": onuID}, err).Log()
2015 }
2016 //clear PON resources associated with ONU
2017 var onuGemData []rsrcMgr.OnuGemInfo
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002018 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[IntfID]; !ok {
2019 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002020 "device-id": dh.deviceID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002021 "interface-id": IntfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002022 } else {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002023 if err := onuMgr.GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05302024 logger.Warnw("failed-to-get-onu-info-for-pon-port", log.Fields{
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002025 "device-id": dh.deviceID,
2026 "interface-id": IntfID,
2027 "error": err})
2028 } else {
2029 for i, onu := range onuGemData {
2030 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Shrey Baid807a2a02020-04-09 12:52:45 +05302031 logger.Debugw("onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002032 if err := dh.clearUNIData(ctx, &onu); err != nil {
2033 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
2034 "device-id": dh.deviceID,
2035 "onu-device": onu,
2036 "error": err})
2037 }
2038 // Clear flowids for gem cache.
2039 for _, gem := range onu.GemPorts {
2040 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
2041 }
2042 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
2043 err := onuMgr.AddOnuGemInfo(ctx, IntfID, onuGemData)
2044 if err != nil {
2045 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
2046 "interface-id": IntfID,
2047 "onu-device": onu,
2048 "onu-gem": onuGemData,
2049 "error": err})
2050 //Not returning error on cleanup.
2051 }
2052 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": IntfID, "onu-device": onu, "onugem": onuGemData})
2053 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
2054 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002055 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002056 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002057 }
2058 }
2059 dh.onus.Delete(onuKey)
2060 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2061 return nil
2062}
Girish Gowdracefae192020-03-19 18:14:10 -07002063
2064func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2065 for _, field := range flows.GetOfbFields(flow) {
2066 if field.Type == flows.IN_PORT {
2067 return field.GetPort()
2068 }
2069 }
2070 return InvalidPort
2071}
2072
2073func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2074 for _, action := range flows.GetActions(flow) {
2075 if action.Type == flows.OUTPUT {
2076 if out := action.GetOutput(); out != nil {
2077 return out.GetPort()
2078 }
2079 }
2080 }
2081 return InvalidPort
2082}
2083
2084func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2085 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302086 logger.Debugw("increment-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002087 if inPort != InvalidPort && outPort != InvalidPort {
2088 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2089 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302090 logger.Debugw("increment-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002091
2092 dh.lockDevice.Lock()
2093 defer dh.lockDevice.Unlock()
2094 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2095 if !ok {
2096 flowRemoveData = pendingFlowRemoveData{
2097 pendingFlowRemoveCount: 0,
2098 allFlowsRemoved: make(chan struct{}),
2099 }
2100 }
2101 flowRemoveData.pendingFlowRemoveCount++
2102 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2103
Shrey Baid807a2a02020-04-09 12:52:45 +05302104 logger.Debugw("current-flow-remove-count–increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002105 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2106 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2107 }
2108}
2109
2110func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2111 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302112 logger.Debugw("decrement-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002113 if inPort != InvalidPort && outPort != InvalidPort {
2114 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2115 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302116 logger.Debugw("decrement-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002117
2118 dh.lockDevice.Lock()
2119 defer dh.lockDevice.Unlock()
2120 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302121 logger.Fatalf("flow-remove-key-not-found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002122 } else {
2123 if val.pendingFlowRemoveCount > 0 {
2124 val.pendingFlowRemoveCount--
2125 }
Shrey Baid807a2a02020-04-09 12:52:45 +05302126 logger.Debugw("current-flow-remove-count-after-decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002127 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2128 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2129 // If all flow removes have finished, then close the channel to signal the receiver
2130 // to go ahead with flow adds.
2131 if val.pendingFlowRemoveCount == 0 {
2132 close(val.allFlowsRemoved)
2133 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2134 return
2135 }
2136 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2137 }
2138 }
2139}
2140
2141func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2142 var flowRemoveData pendingFlowRemoveData
2143 var ok bool
2144 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302145 logger.Debugw("wait-for-flow-remove-to-finish-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002146 if inPort != InvalidPort && outPort != InvalidPort {
2147 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2148 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302149 logger.Debugw("wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002150
2151 dh.lockDevice.RLock()
2152 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302153 logger.Debugw("no-pending-flow-to-remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002154 dh.lockDevice.RUnlock()
2155 return
2156 }
2157 dh.lockDevice.RUnlock()
2158
2159 // Wait for all flow removes to finish first
2160 <-flowRemoveData.allFlowsRemoved
2161
Shrey Baid807a2a02020-04-09 12:52:45 +05302162 logger.Debugw("all-flows-cleared--handling-flow-add-now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002163 }
2164}
2165
2166func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2167 inPort := getInPortFromFlow(flow)
2168 outPort := getOutPortFromFlow(flow)
2169
2170 if inPort == InvalidPort || outPort == InvalidPort {
2171 return inPort, outPort
2172 }
2173
2174 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2175 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2176 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2177 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2178 return uniPort, outPort
2179 }
2180 }
2181 } else {
2182 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2183 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2184 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2185 return inPort, uniPort
2186 }
2187 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2188 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2189 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2190 return uniPort, outPort
2191 }
2192 }
2193 }
2194
2195 return InvalidPort, InvalidPort
2196}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002197
2198func extractOmciTransactionID(omciPkt []byte) uint16 {
2199 if len(omciPkt) > 3 {
2200 d := omciPkt[0:2]
2201 transid := binary.BigEndian.Uint16(d)
2202 return transid
2203 }
2204 return 0
2205}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002206
2207// StoreOnuDevice stores the onu parameters to the local cache.
2208func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2209 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2210 dh.onus.Store(onuKey, onuDevice)
2211}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002212
2213func (dh *DeviceHandler) getExtValue(device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
2214 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002215 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002216 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002217 resp := new(voltha.ReturnValues)
2218 valueparam := new(oop.ValueParam)
2219 ctx := context.Background()
2220 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002221 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2222 return nil, err
2223 }
2224 ID = device.ProxyAddress.GetOnuId()
2225 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2226 valueparam.Onu = &Onu
2227 valueparam.Value = value
2228
2229 // This API is unsupported until agent patch is added
2230 resp.Unsupported = uint32(value)
2231 _ = ctx
2232
2233 // Uncomment this code once agent changes are complete and tests
2234 /*
2235 resp, err = dh.Client.GetValue(ctx, valueparam)
2236 if err != nil {
2237 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2238 return nil, err
2239 }
2240 */
2241
2242 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2243 return resp, nil
2244}