blob: 878c6dbc10b1b8e3f5b5999d3f80a06fa79f491d [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 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530312 go dh.updateLocalDevice()
313 return nil
314}
315
316func (dh *DeviceHandler) updateLocalDevice() error {
317 dh.lockDevice.Lock()
318 defer dh.lockDevice.Unlock()
319 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
320 if err != nil || device == nil {
321 logger.Errorf("device", log.Fields{"device-id": dh.device.Id}, err)
322 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
323 }
324 dh.device = device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800325 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530326}
327
328// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800329func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000330 defer logger.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700331 defer func() {
332 dh.lockDevice.Lock()
333 dh.isReadIndicationRoutineActive = false
334 dh.lockDevice.Unlock()
335 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700336 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700337 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700338 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700339 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400340 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530341 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400342 if err != nil || device == nil {
343 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000344 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400345 }
346 // When the device is in DISABLED and Adapter container restarts, we need to
347 // rebuild the locally maintained admin state.
348 if device.AdminState == voltha.AdminState_DISABLED {
349 dh.lockDevice.Lock()
350 dh.adminState = "down"
351 dh.lockDevice.Unlock()
352 }
353
David Bainbridgef5879ca2019-12-13 21:17:54 +0000354 // Create an exponential backoff around re-enabling indications. The
355 // maximum elapsed time for the back off is set to 0 so that we will
356 // continue to retry. The max interval defaults to 1m, but is set
357 // here for code clarity
358 indicationBackoff := backoff.NewExponentialBackOff()
359 indicationBackoff.MaxElapsedTime = 0
360 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700361
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700362 dh.lockDevice.Lock()
363 dh.isReadIndicationRoutineActive = true
364 dh.lockDevice.Unlock()
365
Girish Gowdra3f974912020-03-23 20:35:18 -0700366Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700367 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400368 select {
369 case <-dh.stopIndications:
Shrey Baid807a2a02020-04-09 12:52:45 +0530370 logger.Debugw("stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.deviceID})
Girish Gowdra3f974912020-03-23 20:35:18 -0700371 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400372 default:
373 indication, err := indications.Recv()
374 if err == io.EOF {
Shrey Baid807a2a02020-04-09 12:52:45 +0530375 logger.Infow("eof-for-indications",
376 log.Fields{"err": err,
377 "device-id": dh.deviceID})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400378 // Use an exponential back off to prevent getting into a tight loop
379 duration := indicationBackoff.NextBackOff()
380 if duration == backoff.Stop {
381 // If we reach a maximum then warn and reset the backoff
382 // timer and keep attempting.
Shrey Baid807a2a02020-04-09 12:52:45 +0530383 logger.Warnw("maximum-indication-backoff-reached--resetting-backoff-timer",
384 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
385 "device-id": dh.deviceID})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400386 indicationBackoff.Reset()
387 }
388 time.Sleep(indicationBackoff.NextBackOff())
Girish Gowdra3f974912020-03-23 20:35:18 -0700389 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
390 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400391 }
392 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000393 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530394 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530395 logger.Errorw("read-indication-error",
396 log.Fields{"err": err,
397 "device-id": dh.deviceID})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400398 if dh.adminState == "deleted" {
Shrey Baid807a2a02020-04-09 12:52:45 +0530399 logger.Debug("device-deleted--stopping-the-read-indication-thread")
Girish Gowdra3f974912020-03-23 20:35:18 -0700400 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400401 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700402 // Close the stream, and re-initialize it
403 if err = indications.CloseSend(); err != nil {
404 // Ok to ignore here, because we landed here due to a problem on the stream
405 // In all probability, the closeSend call may fail
Shrey Baid807a2a02020-04-09 12:52:45 +0530406 logger.Debugw("error-closing-send stream--error-ignored",
407 log.Fields{"err": err,
408 "device-id": dh.deviceID})
Girish Gowdra3f974912020-03-23 20:35:18 -0700409 }
410 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
411 return err
412 }
413 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400414 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530415 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400416 // Reset backoff if we have a successful receive
417 indicationBackoff.Reset()
418 dh.lockDevice.RLock()
419 adminState := dh.adminState
420 dh.lockDevice.RUnlock()
421 // When OLT is admin down, ignore all indications.
422 if adminState == "down" && !isIndicationAllowedDuringOltAdminDown(indication) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530423 logger.Debugw("olt-is-admin-down, ignore indication",
424 log.Fields{"indication": indication,
425 "device-id": dh.deviceID})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400426 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400427 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400428 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700429 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700430 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700431 // Close the send stream
432 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700433
Girish Gowdra3f974912020-03-23 20:35:18 -0700434 return nil
435}
436
437func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
438
439 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
440 if err != nil {
441 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
442 }
443 if indications == nil {
444 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
445 }
446
447 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400448}
449
450// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
451func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
452 switch indication.Data.(type) {
453 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
454 return true
455
456 default:
457 return false
458 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700459}
460
David K. Bainbridge794735f2020-02-11 21:01:37 -0800461func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000462 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000463 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530464 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700465 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530466 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700467 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000468 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800469 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530470 return olterrors.NewErrAdapter("failed-indication", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +0530471 "device-id": dh.deviceID,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800472 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000473 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800474 }
475 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700476}
477
David K. Bainbridge794735f2020-02-11 21:01:37 -0800478// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530479func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400480 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700481 switch indication.Data.(type) {
482 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800483 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530484 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800485 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700486 case *oop.Indication_IntfInd:
487 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800488 go func() {
489 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530490 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800491 }
492 }()
Shrey Baid807a2a02020-04-09 12:52:45 +0530493 logger.Infow("received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.deviceID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700494 case *oop.Indication_IntfOperInd:
495 intfOperInd := indication.GetIntfOperInd()
496 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800497 go func() {
498 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530499 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 -0800500 }
501 }()
npujarec5762e2020-01-01 14:08:48 +0530502 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700503 } else if intfOperInd.GetType() == "pon" {
504 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
505 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800506 go func() {
507 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530508 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 -0800509 }
510 }()
kesavand39e0aa32020-01-28 20:58:50 -0500511 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700512 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530513 logger.Infow("received-interface-oper-indication",
514 log.Fields{"interfaceOperInd": intfOperInd,
515 "device-id": dh.deviceID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700516 case *oop.Indication_OnuDiscInd:
517 onuDiscInd := indication.GetOnuDiscInd()
Shrey Baid807a2a02020-04-09 12:52:45 +0530518 logger.Infow("received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.deviceID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700519 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800520 go func() {
521 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530522 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800523 }
524 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700525 case *oop.Indication_OnuInd:
526 onuInd := indication.GetOnuInd()
Shrey Baid807a2a02020-04-09 12:52:45 +0530527 logger.Infow("received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.deviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800528 go func() {
529 if err := dh.onuIndication(onuInd); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530530 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800531 }
532 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700533 case *oop.Indication_OmciInd:
534 omciInd := indication.GetOmciInd()
Shrey Baid807a2a02020-04-09 12:52:45 +0530535 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 -0800536 go func() {
537 if err := dh.omciIndication(omciInd); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530538 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800539 }
540 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700541 case *oop.Indication_PktInd:
542 pktInd := indication.GetPktInd()
Shrey Baid807a2a02020-04-09 12:52:45 +0530543 logger.Infow("received-packet-indication", log.Fields{"PktInd": pktInd, "device-id": dh.deviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800544 go func() {
545 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530546 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.deviceID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800547 }
548 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700549 case *oop.Indication_PortStats:
550 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530551 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700552 case *oop.Indication_FlowStats:
553 flowStats := indication.GetFlowStats()
Shrey Baid807a2a02020-04-09 12:52:45 +0530554 logger.Infow("received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.deviceID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700555 case *oop.Indication_AlarmInd:
556 alarmInd := indication.GetAlarmInd()
Shrey Baid807a2a02020-04-09 12:52:45 +0530557 logger.Infow("received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.deviceID})
Naga Manjunath7615e552019-10-11 22:35:47 +0530558 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700559 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530560}
561
562// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530563func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530564 //starting the stat collector
565 go startCollector(dh)
566
Girish Gowdru0c588b22019-04-23 23:24:56 -0400567 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530568 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400569 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000570 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400571 }
572 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530573}
574
575// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530576func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700577 dh.lockDevice.Lock()
578 defer dh.lockDevice.Unlock()
Shrey Baid807a2a02020-04-09 12:52:45 +0530579 logger.Debugw("do-state-down-start", log.Fields{"device-id": dh.deviceID})
Girish Gowdrud4245152019-05-10 00:47:31 -0400580
npujarec5762e2020-01-01 14:08:48 +0530581 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400582 if err != nil || device == nil {
583 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000584 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400585 }
586
587 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400588
589 //Update the device oper state and connection status
590 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400591 dh.device = cloned
592
David K. Bainbridge794735f2020-02-11 21:01:37 -0800593 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000594 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400595 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400596
597 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530598 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400599 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000600 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400601 }
602 for _, onuDevice := range onuDevices.Items {
603
604 // Update onu state as down in onu adapter
605 onuInd := oop.OnuIndication{}
606 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800607 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700608 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800609 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530610 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800611 "source": "openolt",
612 "onu-indicator": onuInd,
613 "device-type": onuDevice.Type,
614 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700615 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700616 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400617 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700618 /* Discovered ONUs entries need to be cleared , since after OLT
619 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530620 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000621 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700622 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530623}
624
625// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530626func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400627 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800628 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530629 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800630 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000631 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400632 }
633 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530634}
635
636// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530637func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400638 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530639 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400640 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530641}
642
643// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530644func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530645 logger.Debugw("olt-device-connected", log.Fields{"device-id": dh.deviceID})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400646
647 // Case where OLT is disabled and then rebooted.
648 if dh.adminState == "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000649 logger.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530650 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400651 if err != nil || device == nil {
652 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530653 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400654 }
655
656 cloned := proto.Clone(device).(*voltha.Device)
657 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
658 cloned.OperStatus = voltha.OperStatus_UNKNOWN
659 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530660 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530661 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400662 }
663
Chaitrashree G S44124192019-08-07 20:21:36 -0400664 // 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 +0530665 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400666 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530667 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400668 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400669 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
670 // all the modules initialized and ready to handle incoming ONUs.
671
672 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
673 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
674 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400675
676 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800677 go func() {
678 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530679 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800680 }
681 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400682 return nil
683 }
684
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700685 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400686 if err != nil || device == nil {
687 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000688 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400689 }
kesavand39e0aa32020-01-28 20:58:50 -0500690 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500691 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000692 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400693 }
694
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400695 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
696 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400697 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530698
cuilin20187b2a8c32019-03-26 19:52:28 -0700699 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800700 go func() {
701 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530702 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800703 }
704 }()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530705 go dh.updateLocalDevice()
cuilin20187b2a8c32019-03-26 19:52:28 -0700706 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530707}
708
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400709func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
710 deviceInfo, err := dh.populateDeviceInfo()
711
712 if err != nil {
713 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
714 }
715 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
716 // Instantiate resource manager
717 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
718 return olterrors.ErrResourceManagerInstantiating
719 }
720
721 // Instantiate flow manager
722 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
723 return olterrors.ErrResourceManagerInstantiating
724
725 }
726 /* TODO: Instantiate Alarm , stats , BW managers */
727 /* Instantiating Event Manager to handle Alarms and KPIs */
728 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
729
730 // Stats config for new device
731 dh.portStats = NewOpenOltStatsMgr(dh)
732
733 return nil
734
735}
736
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400737func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
738 var err error
739 var deviceInfo *oop.DeviceInfo
740
741 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
742
743 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000744 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400745 }
746 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000747 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400748 }
749
Shrey Baid807a2a02020-04-09 12:52:45 +0530750 logger.Debugw("fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.deviceID})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400751 dh.device.Root = true
752 dh.device.Vendor = deviceInfo.Vendor
753 dh.device.Model = deviceInfo.Model
754 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
755 dh.device.HardwareVersion = deviceInfo.HardwareVersion
756 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
757
758 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000759 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400760 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
761 genmac, err := generateMacFromHost(host)
762 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000763 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400764 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000765 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400766 dh.device.MacAddress = genmac
767 } else {
768 dh.device.MacAddress = deviceInfo.DeviceId
769 }
770
771 // Synchronous call to update device - this method is run in its own go routine
772 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000773 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400774 }
775
776 return deviceInfo, nil
777}
778
Naga Manjunath7615e552019-10-11 22:35:47 +0530779func startCollector(dh *DeviceHandler) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530780 logger.Debugf("starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530781 context := make(map[string]string)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530782 freq := dh.metrics.ToPmConfigs().DefaultFreq
Naga Manjunath7615e552019-10-11 22:35:47 +0530783 for {
784 select {
785 case <-dh.stopCollector:
Shrey Baid807a2a02020-04-09 12:52:45 +0530786 logger.Debugw("stopping-collector-for-olt", log.Fields{"deviceID:": dh.deviceID})
Naga Manjunath7615e552019-10-11 22:35:47 +0530787 return
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530788 case <-time.After(time.Duration(freq) * time.Second):
Naga Manjunath7615e552019-10-11 22:35:47 +0530789 context["oltid"] = dh.deviceID
790 context["devicetype"] = dh.deviceType
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530791 ports := make([]*voltha.Port, len(dh.device.Ports))
792 copy(ports, dh.device.Ports)
793
794 for _, port := range ports {
795 // NNI Stats
796 if port.Type == voltha.Port_ETHERNET_NNI {
797 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
798 cmnni := dh.portStats.collectNNIMetrics(intfID)
799 logger.Debugw("collect-nni-metrics", log.Fields{"metrics": cmnni})
800 go dh.portStats.publishMetrics(cmnni, port, context, dh.deviceID)
801 logger.Debugw("publish-nni-metrics", log.Fields{"nni-port": port.Label})
802 }
803 // PON Stats
804 if port.Type == voltha.Port_PON_OLT {
805 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
806 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
807 cmpon := dh.portStats.collectPONMetrics(intfID)
808 logger.Debugw("collect-pon-metrics", log.Fields{"metrics": cmpon})
809 go dh.portStats.publishMetrics(cmpon, port, context, dh.deviceID)
810 }
811 logger.Debugw("publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500812 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530813 }
814 }
815 }
816}
817
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530819func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400820 dh.transitionMap = NewTransitionMap(dh)
Shrey Baid807a2a02020-04-09 12:52:45 +0530821 logger.Infow("adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530822 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530823
824 // Now, set the initial PM configuration for that device
825 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530826 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530827 }
828
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400829 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530830}
831
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700832//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530833func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700834 return &ic.SwitchCapability{
835 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530836 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700837 HwDesc: "open_pon",
838 SwDesc: "open_pon",
839 SerialNum: dh.device.SerialNumber,
840 },
841 SwitchFeatures: &of.OfpSwitchFeatures{
842 NBuffers: 256,
843 NTables: 2,
844 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
845 of.OfpCapabilities_OFPC_TABLE_STATS |
846 of.OfpCapabilities_OFPC_PORT_STATS |
847 of.OfpCapabilities_OFPC_GROUP_STATS),
848 },
849 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530850}
851
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700852//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530853func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700854 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700855 return &ic.PortCapability{
856 Port: &voltha.LogicalPort{
857 OfpPort: &of.OfpPort{
858 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
859 Config: 0,
860 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700861 Curr: capacity,
862 Advertised: capacity,
863 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700864 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
865 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
866 },
867 DeviceId: dh.device.Id,
868 DevicePortNo: uint32(portNo),
869 },
870 }, nil
871}
872
David K. Bainbridge794735f2020-02-11 21:01:37 -0800873func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530874 logger.Debugw("omci-indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.deviceID})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700875 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700876 var deviceID string
877 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700878
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400879 transid := extractOmciTransactionID(omciInd.Pkt)
Shrey Baid807a2a02020-04-09 12:52:45 +0530880 logger.Debugw("recv-omci-msg", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId, "device-id": dh.deviceID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400881 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
882
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700883 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530884
885 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
886
Shrey Baid807a2a02020-04-09 12:52:45 +0530887 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 -0700888 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700889 kwargs := make(map[string]interface{})
890 kwargs["onu_id"] = omciInd.OnuId
891 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700892
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700893 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
894 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530895 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800896 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000897 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700898 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700899 deviceType = onuDevice.Type
900 deviceID = onuDevice.Id
901 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
902 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530903 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700904 } else {
905 //found in cache
Shrey Baid807a2a02020-04-09 12:52:45 +0530906 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 +0530907 deviceType = onuInCache.(*OnuDevice).deviceType
908 deviceID = onuInCache.(*OnuDevice).deviceID
909 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700910 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700911
912 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800913 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700914 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800915 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530916 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800917 "source": dh.deviceType,
918 "destination": deviceType,
919 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000920 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700921 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800922 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530923}
924
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700925//ProcessInterAdapterMessage sends the proxied messages to the target device
926// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
927// is meant, and then send the unmarshalled omci message to this onu
928func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530929 logger.Debugw("process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700930 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700931 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700932 fromTopic := msg.Header.FromTopic
933 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700934 toDeviceID := msg.Header.ToDeviceId
935 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700936
Shrey Baid807a2a02020-04-09 12:52:45 +0530937 logger.Debugw("omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700938
939 msgBody := msg.GetBody()
940
941 omciMsg := &ic.InterAdapterOmciMessage{}
942 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000943 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700944 }
945
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700946 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700947 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
948 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530949 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800950 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000951 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700952 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530953 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 -0800954 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530955 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800956 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000957 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800958 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700959 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +0530960 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 -0800961 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530962 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800963 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000964 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800965 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700966 }
967
968 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000969 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700970 }
971 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530972}
973
David K. Bainbridge794735f2020-02-11 21:01:37 -0800974func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700975 var intfID uint32
976 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000977 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700978 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700979 intfID = onuDevice.ProxyAddress.GetChannelId()
980 onuID = onuDevice.ProxyAddress.GetOnuId()
981 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700982 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700983 intfID = omciMsg.GetProxyAddress().GetChannelId()
984 onuID = omciMsg.GetProxyAddress().GetOnuId()
985 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700986 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700987 if connectStatus != voltha.ConnectStatus_REACHABLE {
Shrey Baid807a2a02020-04-09 12:52:45 +0530988 logger.Debugw("onu-not-reachable--cannot-send-omci", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800989
Thomas Lee S94109f12020-03-03 16:39:29 +0530990 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800991 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000992 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700993 }
994
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400995 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
996 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700997 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400998 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
999 hex.Encode(hexPkt, omciMsg.Message)
1000 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1001
1002 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1003 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1004 transid := extractOmciTransactionID(omciMsg.Message)
1005 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
1006 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001007
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001008 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
1009 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301010 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001011 "interface-id": intfID,
1012 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001013 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -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) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301019 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 +02001020 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
1021 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
1022 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001023 // TODO: need resource manager
1024 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001025 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301026 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001027 st, _ := status.FromError(err)
1028 if st.Code() == codes.AlreadyExists {
Shrey Baid807a2a02020-04-09 12:52:45 +05301029 logger.Debugw("onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onuID": onuID, "device-id": dh.deviceID})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001030 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301031 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.deviceID}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001032 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001033 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301034 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.deviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -07001035 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001036 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001037}
1038
David K. Bainbridge794735f2020-02-11 21:01:37 -08001039func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001040
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001041 channelID := onuDiscInd.GetIntfId()
1042 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001043
Girish Kumar2ad402b2020-03-20 19:45:12 +00001044 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301045
cuilin20187b2a8c32019-03-26 19:52:28 -07001046 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001047 if sn != "" {
1048 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001049 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001050 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001051 }
1052
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301053 var alarmInd oop.OnuAlarmIndication
1054 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001055 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301056
1057 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1058 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1059 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1060 OnuLosRaise event sent for it */
1061 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1062 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1063 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Shrey Baid807a2a02020-04-09 12:52:45 +05301064 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301065 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1066 "currentIntfId": onuDiscInd.GetIntfId()})
1067 // TODO:: Should we need to ignore raising OnuLosClear event
1068 // when onu connected to different PON?
1069 }
1070 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1071 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1072 alarmInd.LosStatus = statusCheckOff
1073 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1074 }
1075 return true
1076 })
1077
Girish Kumar2ad402b2020-03-20 19:45:12 +00001078 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001079 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001080 }
1081
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001082 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001083
1084 // check the ONU is already know to the OLT
1085 // NOTE the second time the ONU is discovered this should return a device
1086 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1087
1088 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001089 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 -08001090 if e, ok := status.FromError(err); ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001091 logger.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001092 switch e.Code() {
1093 case codes.Internal:
1094 // this probably means NOT FOUND, so just create a new device
1095 onuDevice = nil
1096 case codes.DeadlineExceeded:
1097 // if the call times out, cleanup and exit
1098 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001099 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001100 }
1101 }
1102 }
1103
1104 if onuDevice == nil {
1105 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Girish Kumar2ad402b2020-03-20 19:45:12 +00001106 logger.Infow("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001107 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001108 ponintfid := onuDiscInd.GetIntfId()
1109 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301110 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001111 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001112
Girish Kumar2ad402b2020-03-20 19:45:12 +00001113 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001114
1115 if err != nil {
1116 // if we can't create an ID in resource manager,
1117 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001118 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001119 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001120 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001121 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001122 }
1123
1124 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1125 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001126 dh.discOnus.Delete(sn)
1127 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 +05301128 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001129 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001130 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001131 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001132 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Shrey Baid807a2a02020-04-09 12:52:45 +05301133 logger.Infow("onu-child-device-added",
1134 log.Fields{"onuDevice": onuDevice,
1135 "sn": sn,
1136 "onuID": onuID,
1137 "device-id": dh.deviceID})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001138 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001139
1140 // we can now use the existing ONU Id
1141 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001142 //Insert the ONU into cache to use in OnuIndication.
1143 //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 +05301144 logger.Debugw("onu-discovery-indication-key-create",
1145 log.Fields{"onuID": onuID,
1146 "intfId": onuDiscInd.GetIntfId(),
1147 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001148 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001149
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301150 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301151 dh.onus.Store(onuKey, onuDev)
Shrey Baid807a2a02020-04-09 12:52:45 +05301152 logger.Debugw("new-onu-device-discovered",
1153 log.Fields{"onu": onuDev,
1154 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001155
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301157 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001158 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001159 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001160 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301161 logger.Infow("onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001162 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301163 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001164 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001165 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001166 }
1167 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001168}
1169
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001171 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1172
1173 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001174 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001175 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001176 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001177 foundInCache := false
Shrey Baid807a2a02020-04-09 12:52:45 +05301178 logger.Debugw("onu-indication-key-create",
1179 log.Fields{"onuId": onuInd.OnuId,
1180 "intfId": onuInd.GetIntfId(),
1181 "device-id": dh.deviceID})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001182 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301183
David K. Bainbridge794735f2020-02-11 21:01:37 -08001184 errFields := log.Fields{"device-id": dh.device.Id}
1185
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301186 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1187
Mahir Gunyele77977b2019-06-27 05:36:22 -07001188 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1189 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1191 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001192 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001193 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1194 if serialNumber != "" {
1195 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001197 } else {
1198 kwargs["onu_id"] = onuInd.OnuId
1199 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 errFields["onu-id"] = onuInd.OnuId
1201 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001202 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001203 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001204 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001205
David K. Bainbridge794735f2020-02-11 21:01:37 -08001206 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001207 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001208 }
1209
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 if onuDevice.ParentPortNo != ponPort {
Shrey Baid807a2a02020-04-09 12:52:45 +05301211 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001212 "previousIntfId": onuDevice.ParentPortNo,
1213 "currentIntfId": ponPort})
1214 }
1215
1216 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Shrey Baid807a2a02020-04-09 12:52:45 +05301217 logger.Warnw("onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
1218 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1219 "received-onu-id": onuInd.OnuId,
1220 "device-id": dh.deviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 }
1222 if !foundInCache {
1223 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1224
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301225 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 -08001226
1227 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001228 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001229 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001230 }
1231 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001232}
1233
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001234func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301235 ctx := context.TODO()
Shrey Baid807a2a02020-04-09 12:52:45 +05301236 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 +00001237 if onuInd.AdminState == "down" {
1238 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1239 if onuInd.OperState != "down" {
Shrey Baid807a2a02020-04-09 12:52:45 +05301240 logger.Warnw("onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001241 onuInd.OperState = "down"
1242 }
1243 }
1244
David K. Bainbridge794735f2020-02-11 21:01:37 -08001245 switch onuInd.OperState {
1246 case "down":
Shrey Baid807a2a02020-04-09 12:52:45 +05301247 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001248 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301249 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001250 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1251 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301252 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001253 "onu-indicator": onuInd,
1254 "source": "openolt",
1255 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001256 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001257 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 case "up":
Shrey Baid807a2a02020-04-09 12:52:45 +05301259 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 -04001260 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301261 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001262 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1263 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301264 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 "onu-indicator": onuInd,
1266 "source": "openolt",
1267 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001268 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001269 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001270 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001271 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001272 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001273 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001274}
1275
cuilin20187b2a8c32019-03-26 19:52:28 -07001276func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1277 if serialNum != nil {
1278 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001279 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001280 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001281}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001282func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1283 decodedStr, err := hex.DecodeString(serialNum[4:])
1284 if err != nil {
1285 return nil, err
1286 }
1287 return &oop.SerialNumber{
1288 VendorId: []byte(serialNum[:4]),
1289 VendorSpecific: []byte(decodedStr),
1290 }, nil
1291}
cuilin20187b2a8c32019-03-26 19:52:28 -07001292
1293func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1294 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001295 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001296 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1297 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1298 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1299 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1300 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1301 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1302 return tmp
1303}
1304
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001305//UpdateFlowsBulk upates the bulk flow
1306func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301307 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001308}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001309
1310//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001311func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301312 logger.Debugw("getchilddevice",
1313 log.Fields{"pon-port": parentPort,
1314 "onuID": onuID,
1315 "device-id": dh.deviceID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001316 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001317 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001318 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001319 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001320 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001321 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001323 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001324 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301325 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 -08001326 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301327}
1328
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001329// SendPacketInToCore sends packet-in to core
1330// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1331// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001332func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001333 logger.Debugw("send-packet-in-to-core", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301334 "port": logicalPort,
1335 "packet": hex.EncodeToString(packetPayload),
1336 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001337 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001338 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301339 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001340 "source": "adapter",
1341 "destination": "core",
1342 "device-id": dh.device.Id,
1343 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001344 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001345 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301346 logger.Debugw("sent-packet-in-to-core-successfully", log.Fields{
1347 "packet": hex.EncodeToString(packetPayload),
1348 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001349 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001350 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001351}
1352
A R Karthick1f85b802019-10-11 05:06:05 +00001353// AddUniPortToOnu adds the uni port to the onu device
1354func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1355 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301356
1357 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001358 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301359 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1360 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001361 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001362 }
1363 }
1364}
1365
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301367func (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 +05301368 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 +01001369
1370 var errorsList []error
1371
Girish Gowdru0c588b22019-04-23 23:24:56 -04001372 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001373 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001374 dh.incrementActiveFlowRemoveCount(flow)
1375
Shrey Baid807a2a02020-04-09 12:52:45 +05301376 logger.Debugw("removing-flow",
1377 log.Fields{"device-id": device.Id,
1378 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001379 err := dh.flowMgr.RemoveFlow(ctx, flow)
1380 if err != nil {
1381 errorsList = append(errorsList, err)
1382 }
1383
1384 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001385 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301386
1387 for _, flow := range flows.ToAdd.Items {
Shrey Baid807a2a02020-04-09 12:52:45 +05301388 logger.Debugw("adding-flow",
1389 log.Fields{"device-id": device.Id,
1390 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001391 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1392 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001393 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1394 if err != nil {
1395 errorsList = append(errorsList, err)
1396 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301397 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001398 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001399
Girish Gowdracefae192020-03-19 18:14:10 -07001400 // 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 +00001401 if groups != nil {
1402 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001403 err := dh.flowMgr.AddGroup(ctx, group)
1404 if err != nil {
1405 errorsList = append(errorsList, err)
1406 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001407 }
1408 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001409 err := dh.flowMgr.ModifyGroup(ctx, group)
1410 if err != nil {
1411 errorsList = append(errorsList, err)
1412 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001413 }
1414 if len(groups.ToRemove.Items) != 0 {
Shrey Baid807a2a02020-04-09 12:52:45 +05301415 logger.Debugw("group-delete-operation-not-supported", log.Fields{"device-id": dh.deviceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00001416 }
1417 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001418 if len(errorsList) > 0 {
1419 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1420 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301421 logger.Debugw("updated-flows-incrementally-successfully", log.Fields{"device-id": dh.deviceID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001422 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301423}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001424
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001425//DisableDevice disables the given device
1426//It marks the following for the given device:
1427//Device-Handler Admin-State : down
1428//Device Port-State: UNKNOWN
1429//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001430func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001431 /* On device disable ,admin state update has to be done prior sending request to agent since
1432 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001433 dh.lockDevice.Lock()
1434 dh.adminState = "down"
1435 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001436 if dh.Client != nil {
1437 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1438 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001439 dh.lockDevice.Lock()
1440 dh.adminState = "up"
1441 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001442 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001443 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001444 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001445 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301446 logger.Debugw("olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001447 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001448 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301449
1450 dh.discOnus = sync.Map{}
1451 dh.onus = sync.Map{}
1452
Thomas Lee S85f37312020-04-03 17:06:12 +05301453 //stopping the stats collector
1454 dh.stopCollector <- true
1455
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301456 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001457 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001458 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1459 for _, port := range cloned.Ports {
1460 if port.GetType() == voltha.Port_PON_OLT {
1461 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1462 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001463 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001464 }
1465 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001466 }
1467
Shrey Baid807a2a02020-04-09 12:52:45 +05301468 logger.Debugw("disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001469 return nil
1470}
1471
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301472func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001473
1474 // Update onu state as unreachable in onu adapter
1475 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301476 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001477 //get the child device for the parent device
1478 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1479 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301480 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 -04001481 }
1482 if onuDevices != nil {
1483 for _, onuDevice := range onuDevices.Items {
1484 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1485 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1486 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001487 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301488 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001489 }
1490
1491 }
1492 }
1493
1494}
1495
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001496//ReenableDevice re-enables the olt device after disable
1497//It marks the following for the given device:
1498//Device-Handler Admin-State : up
1499//Device Port-State: ACTIVE
1500//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001501func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001502 dh.lockDevice.Lock()
1503 dh.adminState = "up"
1504 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301505
1506 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1507 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301508 dh.lockDevice.Lock()
1509 dh.adminState = "down"
1510 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001511 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301512 }
1513 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001514 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001515
1516 cloned := proto.Clone(device).(*voltha.Device)
1517 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001518
kdarapu1afeceb2020-02-12 01:38:09 -05001519 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001520 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001521 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001522 //Update the device oper status as ACTIVE
1523 cloned.OperStatus = voltha.OperStatus_ACTIVE
1524 dh.device = cloned
1525
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001526 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301527 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001528 "device-id": device.Id,
1529 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001530 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001531 }
kesavand39e0aa32020-01-28 20:58:50 -05001532
Shrey Baid807a2a02020-04-09 12:52:45 +05301533 logger.Debugw("reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001534
1535 return nil
1536}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001537
npujarec5762e2020-01-01 14:08:48 +05301538func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001539 var uniID uint32
1540 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301541 for _, port := range onu.UniPorts {
1542 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001543 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001544 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301545 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301546 logger.Debugw("failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001547 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301548 logger.Debugw("deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301549 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001550 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301551 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001552 }
npujarec5762e2020-01-01 14:08:48 +05301553 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001554 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301555 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301556 logger.Debugw("failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001557 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301558 logger.Debugw("removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301559 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301560 logger.Debugw("failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001561 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301562 logger.Debugw("removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301563 }
npujarec5762e2020-01-01 14:08:48 +05301564 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1565 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301566 logger.Debugw("failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301567 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301568 logger.Debugw("removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301569 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301570 logger.Debugw("failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001571 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001572 }
1573 return nil
1574}
1575
npujarec5762e2020-01-01 14:08:48 +05301576func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001577 nniUniID := -1
1578 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301579
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001580 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001581 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001582 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001583 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301584 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301585 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001586 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001587 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301588 logger.Debugw("nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301589 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301590 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Shrey Baid807a2a02020-04-09 12:52:45 +05301591 logger.Debugw("current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301592 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301593 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301594 }
npujarec5762e2020-01-01 14:08:48 +05301595 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001596 }
npujarec5762e2020-01-01 14:08:48 +05301597 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001598 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301599 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001601}
1602
1603// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
npujarec5762e2020-01-01 14:08:48 +05301604func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301605 logger.Debug("function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001606 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001607 if dh.adminState == "deleted" {
1608 dh.lockDevice.Unlock()
1609 return nil
1610 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001611 dh.adminState = "deleted"
1612 dh.lockDevice.Unlock()
1613 /* Clear the KV store data associated with the all the UNI ports
1614 This clears up flow data and also resource map data for various
1615 other pon resources like alloc_id and gemport_id
1616 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001617 go dh.cleanupDeviceResources(ctx)
Shrey Baid807a2a02020-04-09 12:52:45 +05301618 logger.Debug("removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001619 // Stop the Stats collector
1620 dh.stopCollector <- true
1621 // stop the heartbeat check routine
1622 dh.stopHeartbeatCheck <- true
1623 //Reset the state
1624 if dh.Client != nil {
1625 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
1626 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
1627 }
1628 }
1629 cloned := proto.Clone(device).(*voltha.Device)
1630 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1631 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1632 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1633 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1634 "device-id": device.Id,
1635 "connect-status": cloned.ConnectStatus,
1636 "oper-status": cloned.OperStatus}, err).Log()
1637 }
1638 return nil
1639}
1640func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001641 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301642 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1643 var ponPort uint32
1644 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1645 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301646 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301647 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301648 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001649 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001650 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301651 }
1652 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301653 onuID := make([]uint32, 1)
Shrey Baid807a2a02020-04-09 12:52:45 +05301654 logger.Debugw("onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301655 if err = dh.clearUNIData(ctx, &onu); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301656 logger.Errorw("failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301657 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301658 // Clear flowids for gem cache.
1659 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301660 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301661 }
1662 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301663 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301664 }
npujarec5762e2020-01-01 14:08:48 +05301665 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301666 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301667 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301668 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301669 logger.Errorw("failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001670 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001671 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001672 /* Clear the flows from KV store associated with NNI port.
1673 There are mostly trap rules from NNI port (like LLDP)
1674 */
npujarec5762e2020-01-01 14:08:48 +05301675 if err := dh.clearNNIData(ctx); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301676 logger.Errorw("failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001677 }
A R Karthick1f85b802019-10-11 05:06:05 +00001678
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001679 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301680 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001681 }
A R Karthick1f85b802019-10-11 05:06:05 +00001682
Devmalya Paul495b94a2019-08-27 19:42:00 -04001683 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301684 dh.onus.Range(func(key interface{}, value interface{}) bool {
1685 dh.onus.Delete(key)
1686 return true
1687 })
1688
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001689 /*Delete discovered ONU map for the device*/
1690 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1691 dh.discOnus.Delete(key)
1692 return true
1693 })
1694
Devmalya Paul495b94a2019-08-27 19:42:00 -04001695 return nil
1696}
1697
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001698//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001699func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1700 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001701 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001702 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301703 logger.Debugw("rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001704 return nil
1705}
1706
David K. Bainbridge794735f2020-02-11 21:01:37 -08001707func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301708 logger.Debugw("received-packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001709 "packet-indication": *packetIn,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001710 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001711 "packet": hex.EncodeToString(packetIn.Pkt),
1712 })
npujarec5762e2020-01-01 14:08:48 +05301713 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001714 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001715 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001716 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301717 logger.Debugw("sending-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001718 "logicalPortNum": logicalPortNum,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001719 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001720 "packet": hex.EncodeToString(packetIn.Pkt),
1721 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001722 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301723 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001724 "destination": "core",
1725 "source": dh.deviceType,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001726 "device-id": dh.device.Id,
1727 "packet": hex.EncodeToString(packetIn.Pkt),
1728 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001729 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301730 logger.Debugw("success-sending-packet-in-to-core!", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001731 "packet": hex.EncodeToString(packetIn.Pkt),
Shrey Baid807a2a02020-04-09 12:52:45 +05301732 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001733 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001734 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001735}
1736
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001737// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301738func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001739 logger.Debugw("incoming-packet-out", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301740 "device-id": dh.deviceID,
1741 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001742 "pkt-length": len(packet.Data),
1743 "packet": hex.EncodeToString(packet.Data),
1744 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001745
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001746 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001747 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001748 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1749 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301750 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1751 // Do not packet-out lldp packets on uni port.
1752 // ONOS has no clue about uni/nni ports, it just packets out on all
1753 // available ports on the Logical Switch. It should not be interested
1754 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001755 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1756 "device-id": dh.device.Id,
1757 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301758 return nil
1759 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001760 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1761 if innerEthType == 0x8100 {
1762 // q-in-q 802.1ad or 802.1q double tagged packet.
1763 // slice out the outer tag.
1764 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001765 logger.Debugw("packet-now-single-tagged", log.Fields{
1766 "packetData": hex.EncodeToString(packet.Data),
1767 "device-id": dh.device.Id,
1768 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001769 }
1770 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001771 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1772 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001773 uniID := UniIDFromPortNum(uint32(egressPortNo))
1774
npujarec5762e2020-01-01 14:08:48 +05301775 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001776 if err != nil {
1777 // In this case the openolt agent will receive the gemPortID as 0.
1778 // The agent tries to retrieve the gemPortID in this case.
1779 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001780 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001781 "packet": hex.EncodeToString(packet.Data),
Shrey Baid807a2a02020-04-09 12:52:45 +05301782 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001783 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001784 }
1785
1786 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001787
Girish Kumar2ad402b2020-03-20 19:45:12 +00001788 logger.Debugw("sending-packet-to-onu", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301789 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001790 "IntfId": intfID,
1791 "onuID": onuID,
1792 "uniID": uniID,
1793 "gemPortID": gemPortID,
1794 "packet": hex.EncodeToString(packet.Data),
Shrey Baid807a2a02020-04-09 12:52:45 +05301795 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001796 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001797
npujarec5762e2020-01-01 14:08:48 +05301798 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301799 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001800 "source": "adapter",
1801 "destination": "onu",
1802 "egress-port-number": egressPortNo,
1803 "interface-id": intfID,
1804 "oni-id": onuID,
1805 "uni-id": uniID,
1806 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001807 "packet": hex.EncodeToString(packet.Data),
1808 "device-id": dh.device.Id,
1809 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001810 }
1811 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001812 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1813 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001814 return olterrors.NewErrInvalidValue(log.Fields{
1815 "egress-nni-port": egressPortNo,
1816 "device-id": dh.device.Id,
1817 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001818 }
1819 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001820
Girish Kumar2ad402b2020-03-20 19:45:12 +00001821 logger.Debugw("sending-packet-to-nni", log.Fields{
Shrey Baid807a2a02020-04-09 12:52:45 +05301822 "uplink-pkt": uplinkPkt,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001823 "packet": hex.EncodeToString(packet.Data),
Shrey Baid807a2a02020-04-09 12:52:45 +05301824 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001825 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001826
npujarec5762e2020-01-01 14:08:48 +05301827 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001828 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1829 "packet": hex.EncodeToString(packet.Data),
1830 "device-id": dh.device.Id,
1831 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001832 }
1833 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301834 logger.Warnw("packet-out-to-this-interface-type-not-implemented", log.Fields{
1835 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001836 "egressPortType": egressPortType,
1837 "packet": hex.EncodeToString(packet.Data),
Shrey Baid807a2a02020-04-09 12:52:45 +05301838 "device-id": dh.deviceID,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001839 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001840 }
1841 return nil
1842}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001843
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001844func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1845 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001846}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301847
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001848func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301849 // start the heartbeat check towards the OLT.
1850 var timerCheck *time.Timer
1851
1852 for {
1853 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1854 select {
1855 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001856 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1857 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301858 logger.Warnw("hearbeat-failed", log.Fields{"device-id": dh.deviceID})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301859 if timerCheck == nil {
1860 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001861 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301862 }
1863 } else {
1864 if timerCheck != nil {
1865 if timerCheck.Stop() {
Shrey Baid807a2a02020-04-09 12:52:45 +05301866 logger.Debugw("got-hearbeat-within-timeout", log.Fields{"device-id": dh.deviceID})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301867 }
1868 timerCheck = nil
1869 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301870 logger.Debugw("hearbeat",
1871 log.Fields{"signature": heartBeat,
1872 "device-id": dh.deviceID})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301873 }
1874 cancel()
1875 case <-dh.stopHeartbeatCheck:
Shrey Baid807a2a02020-04-09 12:52:45 +05301876 logger.Debugw("stopping-heart-beat-check", log.Fields{"device-id": dh.deviceID})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301877 return
1878 }
1879 }
1880}
1881
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001882func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1883 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1884 if err != nil || device == nil {
1885 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1886 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301887
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001888 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1889 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1890 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1891 }
1892 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1893 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1894 }
1895 go dh.cleanupDeviceResources(ctx)
1896
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001897 dh.lockDevice.RLock()
1898 // Stop the read indication only if it the routine is active
1899 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1900 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1901 // on next execution of the readIndication routine.
1902 if dh.isReadIndicationRoutineActive {
1903 dh.stopIndications <- true
1904 }
1905 dh.lockDevice.RUnlock()
1906
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001907 dh.transitionMap.Handle(ctx, DeviceInit)
1908
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301909 }
1910}
kesavand39e0aa32020-01-28 20:58:50 -05001911
1912// EnablePort to enable Pon interface
1913func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001914 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001915 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001916}
1917
1918// DisablePort to disable pon interface
1919func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001920 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001921 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001922}
1923
kdarapu1afeceb2020-02-12 01:38:09 -05001924//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1925func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301926 ctx := context.Background()
Shrey Baid807a2a02020-04-09 12:52:45 +05301927 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.deviceID})
kesavand39e0aa32020-01-28 20:58:50 -05001928 if port.GetType() == voltha.Port_ETHERNET_NNI {
1929 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001930 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301931 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301932 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001933 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001934 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001935 }
1936 // fetch interfaceid from PortNo
1937 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1938 ponIntf := &oop.Interface{IntfId: ponID}
1939 var operStatus voltha.OperStatus_Types
1940 if enablePort {
1941 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301942 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001943
1944 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301945 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001946 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001947 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001948 }
1949 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001950 dh.activePorts.Store(ponID, true)
Shrey Baid807a2a02020-04-09 12:52:45 +05301951 logger.Infow("enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001952 } else {
1953 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301954 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001955 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301956 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001957 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001958 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001959 }
1960 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001961 dh.activePorts.Store(ponID, false)
Shrey Baid807a2a02020-04-09 12:52:45 +05301962 logger.Infow("disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001963 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001964 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 +05301965 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001966 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001967 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001968 }
1969 return nil
1970}
1971
kdarapu1afeceb2020-02-12 01:38:09 -05001972//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1973func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001974 cloned := proto.Clone(device).(*voltha.Device)
1975 // Disable the port and update the oper_port_status to core
1976 // if the Admin state of the port is disabled on reboot and re-enable device.
1977 for _, port := range cloned.Ports {
1978 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001979 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301980 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001981 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001982 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001983 }
1984 }
1985 }
1986 return nil
1987}
1988
1989//populateActivePorts to populate activePorts map
1990func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301991 logger.Infow("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001992 for _, port := range device.Ports {
1993 if port.Type == voltha.Port_ETHERNET_NNI {
1994 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001995 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001996 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001997 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001998 }
1999 }
2000 if port.Type == voltha.Port_PON_OLT {
2001 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002002 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002003 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002004 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002005 }
2006 }
2007 }
2008}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002009
2010// ChildDeviceLost deletes ONU and clears pon resources related to it.
2011func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002012 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002013 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2014 onuKey := dh.formOnuKey(IntfID, onuID)
2015 onuDevice, ok := dh.onus.Load(onuKey)
2016 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302017 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002018 log.Fields{
2019 "device-id": dh.deviceID,
2020 "onu-id": onuID,
2021 "interface-id": IntfID}, nil).Log()
2022 }
2023 var sn *oop.SerialNumber
2024 var err error
2025 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302026 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002027 log.Fields{
2028 "devicer-id": dh.deviceID,
2029 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2030 }
2031 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
2032 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302033 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002034 "device-id": dh.deviceID,
2035 "onu-id": onuID}, err).Log()
2036 }
2037 //clear PON resources associated with ONU
2038 var onuGemData []rsrcMgr.OnuGemInfo
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002039 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[IntfID]; !ok {
2040 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002041 "device-id": dh.deviceID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002042 "interface-id": IntfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002043 } else {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002044 if err := onuMgr.GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05302045 logger.Warnw("failed-to-get-onu-info-for-pon-port", log.Fields{
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002046 "device-id": dh.deviceID,
2047 "interface-id": IntfID,
2048 "error": err})
2049 } else {
2050 for i, onu := range onuGemData {
2051 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Shrey Baid807a2a02020-04-09 12:52:45 +05302052 logger.Debugw("onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002053 if err := dh.clearUNIData(ctx, &onu); err != nil {
2054 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
2055 "device-id": dh.deviceID,
2056 "onu-device": onu,
2057 "error": err})
2058 }
2059 // Clear flowids for gem cache.
2060 for _, gem := range onu.GemPorts {
2061 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
2062 }
2063 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
2064 err := onuMgr.AddOnuGemInfo(ctx, IntfID, onuGemData)
2065 if err != nil {
2066 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
2067 "interface-id": IntfID,
2068 "onu-device": onu,
2069 "onu-gem": onuGemData,
2070 "error": err})
2071 //Not returning error on cleanup.
2072 }
2073 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": IntfID, "onu-device": onu, "onugem": onuGemData})
2074 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
2075 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002076 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002077 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002078 }
2079 }
2080 dh.onus.Delete(onuKey)
2081 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2082 return nil
2083}
Girish Gowdracefae192020-03-19 18:14:10 -07002084
2085func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2086 for _, field := range flows.GetOfbFields(flow) {
2087 if field.Type == flows.IN_PORT {
2088 return field.GetPort()
2089 }
2090 }
2091 return InvalidPort
2092}
2093
2094func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2095 for _, action := range flows.GetActions(flow) {
2096 if action.Type == flows.OUTPUT {
2097 if out := action.GetOutput(); out != nil {
2098 return out.GetPort()
2099 }
2100 }
2101 }
2102 return InvalidPort
2103}
2104
2105func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2106 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302107 logger.Debugw("increment-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002108 if inPort != InvalidPort && outPort != InvalidPort {
2109 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2110 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302111 logger.Debugw("increment-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002112
2113 dh.lockDevice.Lock()
2114 defer dh.lockDevice.Unlock()
2115 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2116 if !ok {
2117 flowRemoveData = pendingFlowRemoveData{
2118 pendingFlowRemoveCount: 0,
2119 allFlowsRemoved: make(chan struct{}),
2120 }
2121 }
2122 flowRemoveData.pendingFlowRemoveCount++
2123 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2124
Shrey Baid807a2a02020-04-09 12:52:45 +05302125 logger.Debugw("current-flow-remove-count–increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002126 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2127 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2128 }
2129}
2130
2131func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2132 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302133 logger.Debugw("decrement-flow-remove-count-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002134 if inPort != InvalidPort && outPort != InvalidPort {
2135 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2136 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302137 logger.Debugw("decrement-flow-remove-count-for-subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002138
2139 dh.lockDevice.Lock()
2140 defer dh.lockDevice.Unlock()
2141 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302142 logger.Fatalf("flow-remove-key-not-found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002143 } else {
2144 if val.pendingFlowRemoveCount > 0 {
2145 val.pendingFlowRemoveCount--
2146 }
Shrey Baid807a2a02020-04-09 12:52:45 +05302147 logger.Debugw("current-flow-remove-count-after-decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002148 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2149 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2150 // If all flow removes have finished, then close the channel to signal the receiver
2151 // to go ahead with flow adds.
2152 if val.pendingFlowRemoveCount == 0 {
2153 close(val.allFlowsRemoved)
2154 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2155 return
2156 }
2157 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2158 }
2159 }
2160}
2161
2162func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2163 var flowRemoveData pendingFlowRemoveData
2164 var ok bool
2165 inPort, outPort := getPorts(flow)
Shrey Baid807a2a02020-04-09 12:52:45 +05302166 logger.Debugw("wait-for-flow-remove-to-finish-for-inPort-outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002167 if inPort != InvalidPort && outPort != InvalidPort {
2168 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2169 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Shrey Baid807a2a02020-04-09 12:52:45 +05302170 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 -07002171
2172 dh.lockDevice.RLock()
2173 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Shrey Baid807a2a02020-04-09 12:52:45 +05302174 logger.Debugw("no-pending-flow-to-remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002175 dh.lockDevice.RUnlock()
2176 return
2177 }
2178 dh.lockDevice.RUnlock()
2179
2180 // Wait for all flow removes to finish first
2181 <-flowRemoveData.allFlowsRemoved
2182
Shrey Baid807a2a02020-04-09 12:52:45 +05302183 logger.Debugw("all-flows-cleared--handling-flow-add-now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002184 }
2185}
2186
2187func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2188 inPort := getInPortFromFlow(flow)
2189 outPort := getOutPortFromFlow(flow)
2190
2191 if inPort == InvalidPort || outPort == InvalidPort {
2192 return inPort, outPort
2193 }
2194
2195 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2196 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2197 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2198 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2199 return uniPort, outPort
2200 }
2201 }
2202 } else {
2203 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2204 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2205 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2206 return inPort, uniPort
2207 }
2208 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2209 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2210 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2211 return uniPort, outPort
2212 }
2213 }
2214 }
2215
2216 return InvalidPort, InvalidPort
2217}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002218
2219func extractOmciTransactionID(omciPkt []byte) uint16 {
2220 if len(omciPkt) > 3 {
2221 d := omciPkt[0:2]
2222 transid := binary.BigEndian.Uint16(d)
2223 return transid
2224 }
2225 return 0
2226}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002227
2228// StoreOnuDevice stores the onu parameters to the local cache.
2229func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2230 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2231 dh.onus.Store(onuKey, onuDevice)
2232}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002233
2234func (dh *DeviceHandler) getExtValue(device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
2235 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002236 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002237 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002238 resp := new(voltha.ReturnValues)
2239 valueparam := new(oop.ValueParam)
2240 ctx := context.Background()
2241 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002242 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2243 return nil, err
2244 }
2245 ID = device.ProxyAddress.GetOnuId()
2246 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2247 valueparam.Onu = &Onu
2248 valueparam.Value = value
2249
2250 // This API is unsupported until agent patch is added
2251 resp.Unsupported = uint32(value)
2252 _ = ctx
2253
2254 // Uncomment this code once agent changes are complete and tests
2255 /*
2256 resp, err = dh.Client.GetValue(ctx, valueparam)
2257 if err != nil {
2258 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2259 return nil, err
2260 }
2261 */
2262
2263 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2264 return resp, nil
2265}