blob: 7b5f2a2ffa4b5d64124dc4d2be98818c657c543b [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"
Girish Gowdracefae192020-03-19 18:14:10 -070025 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
cuilin20187b2a8c32019-03-26 19:52:28 -070026 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040027 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070028 "strconv"
29 "strings"
30 "sync"
31 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053032
Chaitrashree G Sb2b62dd2019-07-24 21:47:04 -040033 "google.golang.org/grpc/codes"
34
Matteo Scandolo945e4012019-12-12 14:16:11 -080035 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070036 "github.com/gogo/protobuf/proto"
37 "github.com/golang/protobuf/ptypes"
Esin Karamanccb714b2019-11-29 15:02:06 +000038 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
39 "github.com/opencord/voltha-lib-go/v3/pkg/log"
40 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Thomas Lee S94109f12020-03-03 16:39:29 +053041 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080042 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000043 "github.com/opencord/voltha-protos/v3/go/common"
44 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
45 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
46 oop "github.com/opencord/voltha-protos/v3/go/openolt"
47 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070048 "google.golang.org/grpc"
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -040049 "google.golang.org/grpc/status"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053050)
51
salmansiddiqui7ac62132019-08-22 03:58:50 +000052// Constants for number of retries and for timeout
Manikkaraj kb1d51442019-07-23 10:41:02 -040053const (
salmansiddiqui7ac62132019-08-22 03:58:50 +000054 MaxRetry = 10
55 MaxTimeOutInMs = 500
Girish Gowdracefae192020-03-19 18:14:10 -070056 InvalidPort = 0xffffffff
Manikkaraj kb1d51442019-07-23 10:41:02 -040057)
58
Girish Gowdracefae192020-03-19 18:14:10 -070059// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
60type pendingFlowRemoveDataKey struct {
61 intfID uint32
62 onuID uint32
63 uniID uint32
64}
65
66// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
67// This holds the number of pending flow removes and also a signal channel to
68// to indicate the receiver when all flow removes are handled
69type pendingFlowRemoveData struct {
70 pendingFlowRemoveCount uint32
71 allFlowsRemoved chan struct{}
72}
73
Phaneendra Manda4c62c802019-03-06 21:37:49 +053074//DeviceHandler will interact with the OLT device.
75type DeviceHandler struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070076 deviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -070077 deviceType string
Girish Gowdru5ba46c92019-04-25 05:00:05 -040078 adminState string
cuilin20187b2a8c32019-03-26 19:52:28 -070079 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053080 coreProxy adapterif.CoreProxy
81 AdapterProxy adapterif.AdapterProxy
82 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070083 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070084 exitChannel chan int
85 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053086 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070087 transitionMap *TransitionMap
88 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053089 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040090 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053091 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053092
Girish Gowdra3ab6d212020-03-24 17:33:15 -070093 discOnus sync.Map
94 onus sync.Map
95 portStats *OpenOltStatisticsMgr
96 metrics *pmmetrics.PmMetrics
97 stopCollector chan bool
98 stopHeartbeatCheck chan bool
99 activePorts sync.Map
100 stopIndications chan bool
101 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -0700102
103 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
104 // subscriber basis for the number of pending flow removes. This data is used
105 // to process all the flow removes for a subscriber before handling flow adds.
106 // Interleaving flow delete and flow add processing has known to cause PON resource
107 // management contentions on a per subscriber bases, so we need ensure ordering.
108 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109}
110
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700112type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700114 deviceType string
115 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700116 onuID uint32
117 intfID uint32
118 proxyDeviceID string
A R Karthick1f85b802019-10-11 05:06:05 +0000119 uniPorts map[uint32]struct{}
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530120 losRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700121}
122
Naga Manjunath7615e552019-10-11 22:35:47 +0530123var pmNames = []string{
124 "rx_bytes",
125 "rx_packets",
126 "rx_mcast_packets",
127 "rx_bcast_packets",
128 "tx_bytes",
129 "tx_packets",
130 "tx_mcast_packets",
131 "tx_bcast_packets",
132}
133
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700134//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530135func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700136 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700137 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700138 device.deviceType = deviceTp
139 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 device.onuID = onuID
141 device.intfID = intfID
142 device.proxyDeviceID = proxyDevID
A R Karthick1f85b802019-10-11 05:06:05 +0000143 device.uniPorts = make(map[uint32]struct{})
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530144 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700145 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530146}
147
148//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530149func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700150 var dh DeviceHandler
151 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400152 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400153 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700154 cloned := (proto.Clone(device)).(*voltha.Device)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700155 dh.deviceID = cloned.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700156 dh.deviceType = cloned.Type
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400157 dh.adminState = "up"
cuilin20187b2a8c32019-03-26 19:52:28 -0700158 dh.device = cloned
159 dh.openOLT = adapter
160 dh.exitChannel = make(chan int, 1)
161 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530162 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530163 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530164 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 -0500165 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400166 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700167 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
168
cuilin20187b2a8c32019-03-26 19:52:28 -0700169 //TODO initialize the support classes.
170 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530171}
172
173// start save the device to the data model
174func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700175 dh.lockDevice.Lock()
176 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000177 logger.Debugw("starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700178 // Add the initial device to the local model
Girish Kumar2ad402b2020-03-20 19:45:12 +0000179 logger.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530180}
181
182// stop stops the device dh. Not much to do for now
183func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700184 dh.lockDevice.Lock()
185 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000186 logger.Debug("stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700187 dh.exitChannel <- 1
Girish Kumar2ad402b2020-03-20 19:45:12 +0000188 logger.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530189}
190
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400191func macifyIP(ip net.IP) string {
192 if len(ip) > 0 {
193 oct1 := strconv.FormatInt(int64(ip[12]), 16)
194 oct2 := strconv.FormatInt(int64(ip[13]), 16)
195 oct3 := strconv.FormatInt(int64(ip[14]), 16)
196 oct4 := strconv.FormatInt(int64(ip[15]), 16)
197 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
198 }
199 return ""
200}
201
202func generateMacFromHost(host string) (string, error) {
203 var genmac string
204 var addr net.IP
205 var ips []string
206 var err error
207
Girish Kumar2ad402b2020-03-20 19:45:12 +0000208 logger.Debugw("generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400209
210 if addr = net.ParseIP(host); addr == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000211 logger.Debugw("looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400212
213 if ips, err = net.LookupHost(host); err == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000214 logger.Debugw("dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400215 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000216 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400217 }
218 genmac = macifyIP(addr)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000219 logger.Debugw("using-ip-as-mac", log.Fields{"host": ips[0], "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400220 return genmac, nil
221 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000222 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400223 }
224
225 genmac = macifyIP(addr)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000226 logger.Debugw("using-ip-as-mac", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400227 return genmac, nil
228}
229
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530230func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700231 slist := strings.Split(mac, ":")
232 result := make([]uint32, len(slist))
233 var err error
234 var tmp int64
235 for index, val := range slist {
236 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
237 return []uint32{1, 2, 3, 4, 5, 6}
238 }
239 result[index] = uint32(tmp)
240 }
241 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530242}
243
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700244//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 -0800245func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530246
David K. Bainbridge794735f2020-02-11 21:01:37 -0800247 switch portType {
248 case voltha.Port_ETHERNET_NNI:
249 return fmt.Sprintf("nni-%d", portNum), nil
250 case voltha.Port_PON_OLT:
251 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700252 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800253
Girish Kumarf26e4882020-03-05 06:49:10 +0000254 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530255}
256
David K. Bainbridge794735f2020-02-11 21:01:37 -0800257func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000258 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700259 if state == "up" {
260 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500261 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500262 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700263 } else {
264 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500265 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700266 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700267 portNum := IntfIDToPortNo(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800268 label, err := GetportLabel(portNum, portType)
269 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000270 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400271 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500272
273 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
274 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000275 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500276 }
277 if device.Ports != nil {
278 for _, dPort := range device.Ports {
279 if dPort.Type == portType && dPort.PortNo == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000280 logger.Debug("port-already-exists-updating-oper-status-of-port")
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500281 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530282 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800283 "device-id": dh.device.Id,
284 "port-type": portType,
285 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000286 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800287
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500288 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800289 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500290 }
291 }
292 }
Girish Gowdru0c588b22019-04-23 23:24:56 -0400293 // Now create Port
294 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700295 PortNo: portNum,
296 Label: label,
297 Type: portType,
298 OperStatus: operStatus,
299 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000300 logger.Debugw("Sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700301 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700302 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000303 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800304 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000305 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400306 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800307 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530308}
309
310// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800311func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000312 defer logger.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700313 defer func() {
314 dh.lockDevice.Lock()
315 dh.isReadIndicationRoutineActive = false
316 dh.lockDevice.Unlock()
317 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700318 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700319 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700320 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700321 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400322 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530323 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400324 if err != nil || device == nil {
325 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000326 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400327 }
328 // When the device is in DISABLED and Adapter container restarts, we need to
329 // rebuild the locally maintained admin state.
330 if device.AdminState == voltha.AdminState_DISABLED {
331 dh.lockDevice.Lock()
332 dh.adminState = "down"
333 dh.lockDevice.Unlock()
334 }
335
David Bainbridgef5879ca2019-12-13 21:17:54 +0000336 // Create an exponential backoff around re-enabling indications. The
337 // maximum elapsed time for the back off is set to 0 so that we will
338 // continue to retry. The max interval defaults to 1m, but is set
339 // here for code clarity
340 indicationBackoff := backoff.NewExponentialBackOff()
341 indicationBackoff.MaxElapsedTime = 0
342 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700343
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700344 dh.lockDevice.Lock()
345 dh.isReadIndicationRoutineActive = true
346 dh.lockDevice.Unlock()
347
Girish Gowdra3f974912020-03-23 20:35:18 -0700348Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700349 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400350 select {
351 case <-dh.stopIndications:
Girish Kumar2ad402b2020-03-20 19:45:12 +0000352 logger.Debugw("Stopping-collecting-indications-for-OLT", log.Fields{"deviceID:": dh.deviceID})
Girish Gowdra3f974912020-03-23 20:35:18 -0700353 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400354 default:
355 indication, err := indications.Recv()
356 if err == io.EOF {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000357 logger.Infow("EOF for indications", log.Fields{"err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400358 // Use an exponential back off to prevent getting into a tight loop
359 duration := indicationBackoff.NextBackOff()
360 if duration == backoff.Stop {
361 // If we reach a maximum then warn and reset the backoff
362 // timer and keep attempting.
Girish Kumar2ad402b2020-03-20 19:45:12 +0000363 logger.Warnw("Maximum indication backoff reached, resetting backoff timer",
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400364 log.Fields{"max_indication_backoff": indicationBackoff.MaxElapsedTime})
365 indicationBackoff.Reset()
366 }
367 time.Sleep(indicationBackoff.NextBackOff())
Girish Gowdra3f974912020-03-23 20:35:18 -0700368 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
369 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400370 }
371 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000372 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530373 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700374 logger.Errorw("Read indication error", log.Fields{"err": err})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400375 if dh.adminState == "deleted" {
Girish Gowdra3f974912020-03-23 20:35:18 -0700376 logger.Debug("Device deleted stopping the read indication thread")
377 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400378 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700379 // Close the stream, and re-initialize it
380 if err = indications.CloseSend(); err != nil {
381 // Ok to ignore here, because we landed here due to a problem on the stream
382 // In all probability, the closeSend call may fail
383 logger.Debugw("error closing send stream, error ignored", log.Fields{"err": err})
384 }
385 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
386 return err
387 }
388 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400389 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530390 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400391 // Reset backoff if we have a successful receive
392 indicationBackoff.Reset()
393 dh.lockDevice.RLock()
394 adminState := dh.adminState
395 dh.lockDevice.RUnlock()
396 // When OLT is admin down, ignore all indications.
397 if adminState == "down" && !isIndicationAllowedDuringOltAdminDown(indication) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000398 logger.Debugw("olt is admin down, ignore indication", log.Fields{"indication": indication})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400399 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400400 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400401 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700402 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700403 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700404 // Close the send stream
405 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700406
Girish Gowdra3f974912020-03-23 20:35:18 -0700407 return nil
408}
409
410func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
411
412 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
413 if err != nil {
414 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
415 }
416 if indications == nil {
417 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
418 }
419
420 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400421}
422
423// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
424func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
425 switch indication.Data.(type) {
426 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
427 return true
428
429 default:
430 return false
431 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700432}
433
David K. Bainbridge794735f2020-02-11 21:01:37 -0800434func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000435 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000436 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530437 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700438 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530439 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700440 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000441 // Send or clear Alarm
David K. Bainbridge794735f2020-02-11 21:01:37 -0800442 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.deviceID, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530443 return olterrors.NewErrAdapter("failed-indication", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800444 "device_id": dh.deviceID,
445 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000446 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800447 }
448 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700449}
450
David K. Bainbridge794735f2020-02-11 21:01:37 -0800451// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530452func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400453 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700454 switch indication.Data.(type) {
455 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800456 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530457 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800458 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700459 case *oop.Indication_IntfInd:
460 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800461 go func() {
462 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530463 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800464 }
465 }()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000466 logger.Infow("Received interface indication ", log.Fields{"InterfaceInd": intfInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700467 case *oop.Indication_IntfOperInd:
468 intfOperInd := indication.GetIntfOperInd()
469 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800470 go func() {
471 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530472 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800473 }
474 }()
npujarec5762e2020-01-01 14:08:48 +0530475 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700476 } else if intfOperInd.GetType() == "pon" {
477 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
478 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800479 go func() {
480 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530481 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800482 }
483 }()
kesavand39e0aa32020-01-28 20:58:50 -0500484 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700485 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000486 logger.Infow("Received interface oper indication ", log.Fields{"InterfaceOperInd": intfOperInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700487 case *oop.Indication_OnuDiscInd:
488 onuDiscInd := indication.GetOnuDiscInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000489 logger.Infow("Received Onu discovery indication ", log.Fields{"OnuDiscInd": onuDiscInd})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700490 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800491 go func() {
492 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530493 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800494 }
495 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700496 case *oop.Indication_OnuInd:
497 onuInd := indication.GetOnuInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000498 logger.Infow("Received Onu indication ", log.Fields{"OnuInd": onuInd})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800499 go func() {
500 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530501 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800502 }
503 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700504 case *oop.Indication_OmciInd:
505 omciInd := indication.GetOmciInd()
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400506 logger.Debugw("Received Omci indication ", log.Fields{"IntfId": omciInd.IntfId, "OnuId": omciInd.OnuId})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800507 go func() {
508 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530509 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800510 }
511 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700512 case *oop.Indication_PktInd:
513 pktInd := indication.GetPktInd()
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700514 logger.Debugw("Received packet indication ", log.Fields{"PktInd": pktInd, "deviceId": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800515 go func() {
516 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530517 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet"}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800518 }
519 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700520 case *oop.Indication_PortStats:
521 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530522 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700523 case *oop.Indication_FlowStats:
524 flowStats := indication.GetFlowStats()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000525 logger.Infow("Received flow stats", log.Fields{"FlowStats": flowStats})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700526 case *oop.Indication_AlarmInd:
527 alarmInd := indication.GetAlarmInd()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000528 logger.Infow("Received alarm indication ", log.Fields{"AlarmInd": alarmInd})
Naga Manjunath7615e552019-10-11 22:35:47 +0530529 go dh.eventMgr.ProcessEvents(alarmInd, dh.deviceID, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700530 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530531}
532
533// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530534func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530535 //starting the stat collector
536 go startCollector(dh)
537
Girish Gowdru0c588b22019-04-23 23:24:56 -0400538 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530539 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400540 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000541 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400542 }
543 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530544}
545
546// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530547func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700548 dh.lockDevice.Lock()
549 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000550 logger.Debug("do-state-down-start")
Girish Gowdrud4245152019-05-10 00:47:31 -0400551
npujarec5762e2020-01-01 14:08:48 +0530552 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400553 if err != nil || device == nil {
554 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000555 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400556 }
557
558 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400559
560 //Update the device oper state and connection status
561 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400562 dh.device = cloned
563
David K. Bainbridge794735f2020-02-11 21:01:37 -0800564 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000565 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400566 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400567
568 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530569 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400570 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000571 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400572 }
573 for _, onuDevice := range onuDevices.Items {
574
575 // Update onu state as down in onu adapter
576 onuInd := oop.OnuIndication{}
577 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800578 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700579 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800580 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530581 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800582 "source": "openolt",
583 "onu-indicator": onuInd,
584 "device-type": onuDevice.Type,
585 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700586 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700587 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400588 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700589 /* Discovered ONUs entries need to be cleared , since after OLT
590 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530591 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000592 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700593 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530594}
595
596// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530597func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400598 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800599 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530600 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800601 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000602 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400603 }
604 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530605}
606
607// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530608func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400609 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530610 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400611 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530612}
613
614// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530615func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000616 logger.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400617
618 // Case where OLT is disabled and then rebooted.
619 if dh.adminState == "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000620 logger.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530621 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400622 if err != nil || device == nil {
623 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530624 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400625 }
626
627 cloned := proto.Clone(device).(*voltha.Device)
628 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
629 cloned.OperStatus = voltha.OperStatus_UNKNOWN
630 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530631 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530632 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400633 }
634
Chaitrashree G S44124192019-08-07 20:21:36 -0400635 // 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 +0530636 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400637 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530638 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400639 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400640 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
641 // all the modules initialized and ready to handle incoming ONUs.
642
643 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
644 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
645 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400646
647 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800648 go func() {
649 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530650 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800651 }
652 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400653 return nil
654 }
655
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400657 if err != nil || device == nil {
658 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000659 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400660 }
kesavand39e0aa32020-01-28 20:58:50 -0500661 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500662 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000663 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400664 }
665
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400666 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
667 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400668 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530669
cuilin20187b2a8c32019-03-26 19:52:28 -0700670 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 go func() {
672 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530673 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800674 }
675 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700676 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530677}
678
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400679func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
680 deviceInfo, err := dh.populateDeviceInfo()
681
682 if err != nil {
683 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
684 }
685 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
686 // Instantiate resource manager
687 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
688 return olterrors.ErrResourceManagerInstantiating
689 }
690
691 // Instantiate flow manager
692 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
693 return olterrors.ErrResourceManagerInstantiating
694
695 }
696 /* TODO: Instantiate Alarm , stats , BW managers */
697 /* Instantiating Event Manager to handle Alarms and KPIs */
698 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
699
700 // Stats config for new device
701 dh.portStats = NewOpenOltStatsMgr(dh)
702
703 return nil
704
705}
706
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400707func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
708 var err error
709 var deviceInfo *oop.DeviceInfo
710
711 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
712
713 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000714 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400715 }
716 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000717 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400718 }
719
Girish Kumar2ad402b2020-03-20 19:45:12 +0000720 logger.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400721 dh.device.Root = true
722 dh.device.Vendor = deviceInfo.Vendor
723 dh.device.Model = deviceInfo.Model
724 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
725 dh.device.HardwareVersion = deviceInfo.HardwareVersion
726 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
727
728 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000729 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400730 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
731 genmac, err := generateMacFromHost(host)
732 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000733 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400734 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000735 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400736 dh.device.MacAddress = genmac
737 } else {
738 dh.device.MacAddress = deviceInfo.DeviceId
739 }
740
741 // Synchronous call to update device - this method is run in its own go routine
742 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000743 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400744 }
745
746 return deviceInfo, nil
747}
748
Naga Manjunath7615e552019-10-11 22:35:47 +0530749func startCollector(dh *DeviceHandler) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000750 logger.Debugf("Starting-Collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530751 context := make(map[string]string)
752 for {
753 select {
754 case <-dh.stopCollector:
Girish Kumar2ad402b2020-03-20 19:45:12 +0000755 logger.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
Naga Manjunath7615e552019-10-11 22:35:47 +0530756 return
757 default:
758 freq := dh.metrics.ToPmConfigs().DefaultFreq
759 time.Sleep(time.Duration(freq) * time.Second)
760 context["oltid"] = dh.deviceID
761 context["devicetype"] = dh.deviceType
762 // NNI Stats
763 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
Girish Kumar2ad402b2020-03-20 19:45:12 +0000764 logger.Debugf("Collect-NNI-Metrics %v", cmnni)
Naga Manjunath7615e552019-10-11 22:35:47 +0530765 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000766 logger.Debugf("Publish-NNI-Metrics")
Naga Manjunath7615e552019-10-11 22:35:47 +0530767 // PON Stats
768 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500769 for i := uint32(0); i < NumPonPORTS; i++ {
770 if val, ok := dh.activePorts.Load(i); ok && val == true {
771 cmpon := dh.portStats.collectPONMetrics(i)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000772 logger.Debugf("Collect-PON-Metrics %v", cmpon)
Chaitrashree G Sef088112020-02-03 21:39:27 -0500773 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000774 logger.Debugf("Publish-PON-Metrics")
Chaitrashree G Sef088112020-02-03 21:39:27 -0500775 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530776 }
777 }
778 }
779}
780
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700781//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530782func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400783 dh.transitionMap = NewTransitionMap(dh)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000784 logger.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530785 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530786
787 // Now, set the initial PM configuration for that device
788 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530789 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530790 }
791
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400792 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530793}
794
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700795//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530796func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700797 return &ic.SwitchCapability{
798 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530799 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700800 HwDesc: "open_pon",
801 SwDesc: "open_pon",
802 SerialNum: dh.device.SerialNumber,
803 },
804 SwitchFeatures: &of.OfpSwitchFeatures{
805 NBuffers: 256,
806 NTables: 2,
807 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
808 of.OfpCapabilities_OFPC_TABLE_STATS |
809 of.OfpCapabilities_OFPC_PORT_STATS |
810 of.OfpCapabilities_OFPC_GROUP_STATS),
811 },
812 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530813}
814
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700815//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530816func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700817 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700818 return &ic.PortCapability{
819 Port: &voltha.LogicalPort{
820 OfpPort: &of.OfpPort{
821 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
822 Config: 0,
823 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700824 Curr: capacity,
825 Advertised: capacity,
826 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700827 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
828 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
829 },
830 DeviceId: dh.device.Id,
831 DevicePortNo: uint32(portNo),
832 },
833 }, nil
834}
835
David K. Bainbridge794735f2020-02-11 21:01:37 -0800836func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000837 logger.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700838 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700839 var deviceID string
840 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700841
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400842 transid := extractOmciTransactionID(omciInd.Pkt)
843 logger.Debugw("recv-omci-msg", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId,
844 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
845
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700846 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530847
848 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
849
Girish Kumar2ad402b2020-03-20 19:45:12 +0000850 logger.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700851 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700852 kwargs := make(map[string]interface{})
853 kwargs["onu_id"] = omciInd.OnuId
854 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700855
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700856 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
857 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530858 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800859 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000860 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700861 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700862 deviceType = onuDevice.Type
863 deviceID = onuDevice.Id
864 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
865 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530866 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700867 } else {
868 //found in cache
Girish Kumar2ad402b2020-03-20 19:45:12 +0000869 logger.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530870 deviceType = onuInCache.(*OnuDevice).deviceType
871 deviceID = onuInCache.(*OnuDevice).deviceID
872 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700873 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700874
875 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800876 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700877 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800878 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530879 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800880 "source": dh.deviceType,
881 "destination": deviceType,
882 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000883 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700884 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800885 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530886}
887
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700888//ProcessInterAdapterMessage sends the proxied messages to the target device
889// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
890// is meant, and then send the unmarshalled omci message to this onu
891func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000892 logger.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700893 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700894 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700895 fromTopic := msg.Header.FromTopic
896 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700897 toDeviceID := msg.Header.ToDeviceId
898 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700899
Girish Kumar2ad402b2020-03-20 19:45:12 +0000900 logger.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700901
902 msgBody := msg.GetBody()
903
904 omciMsg := &ic.InterAdapterOmciMessage{}
905 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000906 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700907 }
908
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700909 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700910 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
911 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530912 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800913 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000914 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700915 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000916 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 -0800917 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530918 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800919 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000920 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800921 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700922 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000923 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 -0800924 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530925 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800926 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000927 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800928 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700929 }
930
931 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000932 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700933 }
934 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530935}
936
David K. Bainbridge794735f2020-02-11 21:01:37 -0800937func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938 var intfID uint32
939 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000940 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700941 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 intfID = onuDevice.ProxyAddress.GetChannelId()
943 onuID = onuDevice.ProxyAddress.GetOnuId()
944 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700945 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700946 intfID = omciMsg.GetProxyAddress().GetChannelId()
947 onuID = omciMsg.GetProxyAddress().GetOnuId()
948 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700949 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700950 if connectStatus != voltha.ConnectStatus_REACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000951 logger.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800952
Thomas Lee S94109f12020-03-03 16:39:29 +0530953 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800954 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000955 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700956 }
957
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400958 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
959 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700960 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400961 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
962 hex.Encode(hexPkt, omciMsg.Message)
963 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
964
965 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
966 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
967 transid := extractOmciTransactionID(omciMsg.Message)
968 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
969 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700970
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700971 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
972 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530973 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800974 "interface-id": intfID,
975 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000976 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700977 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800978 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700979}
980
David K. Bainbridge794735f2020-02-11 21:01:37 -0800981func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000982 logger.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
Andrea Campanellab83b39d2020-03-30 11:41:16 +0200983 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
984 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
985 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700986 // TODO: need resource manager
987 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530989 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400990 st, _ := status.FromError(err)
991 if st.Code() == codes.AlreadyExists {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000992 logger.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400993 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000994 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400995 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700996 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000997 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
cuilin20187b2a8c32019-03-26 19:52:28 -0700998 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800999 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001000}
1001
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001003
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001004 channelID := onuDiscInd.GetIntfId()
1005 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001006
Girish Kumar2ad402b2020-03-20 19:45:12 +00001007 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301008
cuilin20187b2a8c32019-03-26 19:52:28 -07001009 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001010 if sn != "" {
1011 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001012 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001013 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001014 }
1015
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301016 var alarmInd oop.OnuAlarmIndication
1017 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001018 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301019
1020 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1021 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1022 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1023 OnuLosRaise event sent for it */
1024 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1025 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1026 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001027 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301028 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1029 "currentIntfId": onuDiscInd.GetIntfId()})
1030 // TODO:: Should we need to ignore raising OnuLosClear event
1031 // when onu connected to different PON?
1032 }
1033 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1034 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1035 alarmInd.LosStatus = statusCheckOff
1036 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1037 }
1038 return true
1039 })
1040
Girish Kumar2ad402b2020-03-20 19:45:12 +00001041 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001043 }
1044
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001045 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001046
1047 // check the ONU is already know to the OLT
1048 // NOTE the second time the ONU is discovered this should return a device
1049 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1050
1051 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001052 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 -08001053 if e, ok := status.FromError(err); ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001054 logger.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001055 switch e.Code() {
1056 case codes.Internal:
1057 // this probably means NOT FOUND, so just create a new device
1058 onuDevice = nil
1059 case codes.DeadlineExceeded:
1060 // if the call times out, cleanup and exit
1061 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001062 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001063 }
1064 }
1065 }
1066
1067 if onuDevice == nil {
1068 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Girish Kumar2ad402b2020-03-20 19:45:12 +00001069 logger.Infow("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001070 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001071 ponintfid := onuDiscInd.GetIntfId()
1072 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301073 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001074 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001075
Girish Kumar2ad402b2020-03-20 19:45:12 +00001076 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001077
1078 if err != nil {
1079 // if we can't create an ID in resource manager,
1080 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001081 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001082 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001084 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001085 }
1086
1087 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1088 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001089 dh.discOnus.Delete(sn)
1090 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 +05301091 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001092 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001093 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001094 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001095 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Girish Kumar2ad402b2020-03-20 19:45:12 +00001096 logger.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001097 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001098
1099 // we can now use the existing ONU Id
1100 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001101 //Insert the ONU into cache to use in OnuIndication.
1102 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001103 logger.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
Matteo Scandolo945e4012019-12-12 14:16:11 -08001104 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001105 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001106
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301107 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301108 dh.onus.Store(onuKey, onuDev)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001109 logger.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001110
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301112 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001114 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001115 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001116 logger.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001117 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301118 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001119 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001120 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001121 }
1122 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001123}
1124
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001126 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1127
1128 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001129 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001130 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001131 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001132 foundInCache := false
Girish Kumar2ad402b2020-03-20 19:45:12 +00001133 logger.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
Scott Baker7eb0a932019-07-26 10:33:22 -07001134 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001135 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301136
David K. Bainbridge794735f2020-02-11 21:01:37 -08001137 errFields := log.Fields{"device-id": dh.device.Id}
1138
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301139 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1140
Mahir Gunyele77977b2019-06-27 05:36:22 -07001141 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1142 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001143 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1144 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001145 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001146 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1147 if serialNumber != "" {
1148 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001150 } else {
1151 kwargs["onu_id"] = onuInd.OnuId
1152 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 errFields["onu-id"] = onuInd.OnuId
1154 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001155 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001157 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001158
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001160 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001161 }
1162
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 if onuDevice.ParentPortNo != ponPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001164 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 "previousIntfId": onuDevice.ParentPortNo,
1166 "currentIntfId": ponPort})
1167 }
1168
1169 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001170 logger.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1172 "received_onu_id": onuInd.OnuId})
1173 }
1174 if !foundInCache {
1175 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1176
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301177 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 -08001178
1179 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001180 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001181 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001182 }
1183 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001184}
1185
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001186func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301187 ctx := context.TODO()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001188 logger.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001189 if onuInd.AdminState == "down" {
1190 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1191 if onuInd.OperState != "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001192 logger.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001193 onuInd.OperState = "down"
1194 }
1195 }
1196
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 switch onuInd.OperState {
1198 case "down":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001199 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001200 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301201 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001202 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1203 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301204 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001205 "onu-indicator": onuInd,
1206 "source": "openolt",
1207 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001208 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001209 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 case "up":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001211 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Matt Jeanneret53539512019-07-20 14:47:02 -04001212 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301213 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001214 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1215 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301216 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001217 "onu-indicator": onuInd,
1218 "source": "openolt",
1219 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001220 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001221 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001223 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001224 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001225 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001226}
1227
cuilin20187b2a8c32019-03-26 19:52:28 -07001228func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1229 if serialNum != nil {
1230 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001231 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001232 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001233}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001234func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1235 decodedStr, err := hex.DecodeString(serialNum[4:])
1236 if err != nil {
1237 return nil, err
1238 }
1239 return &oop.SerialNumber{
1240 VendorId: []byte(serialNum[:4]),
1241 VendorSpecific: []byte(decodedStr),
1242 }, nil
1243}
cuilin20187b2a8c32019-03-26 19:52:28 -07001244
1245func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1246 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001247 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001248 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1249 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1250 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1251 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1252 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1253 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1254 return tmp
1255}
1256
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001257//UpdateFlowsBulk upates the bulk flow
1258func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301259 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001260}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001261
1262//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001264 logger.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001265 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001266 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001267 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001268 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001269 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001270 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001271 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001272 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001273 }
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001274 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 -08001275 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301276}
1277
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001278// SendPacketInToCore sends packet-in to core
1279// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1280// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001282 logger.Debugw("send-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001283 "port": logicalPort,
1284 "packet": hex.EncodeToString(packetPayload),
1285 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001286 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301287 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001288 "source": "adapter",
1289 "destination": "core",
1290 "device-id": dh.device.Id,
1291 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001292 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001293 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001294 logger.Debugw("Sent packet-in to core successfully", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001295 "packet": hex.EncodeToString(packetPayload),
1296 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001297 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001298}
1299
A R Karthick1f85b802019-10-11 05:06:05 +00001300// AddUniPortToOnu adds the uni port to the onu device
1301func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1302 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301303
1304 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001305 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301306 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1307 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001308 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001309 }
1310 }
1311}
1312
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001313//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301314func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001315 logger.Debugw("Received-incremental-flowupdate-in-device-handler", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001316
1317 var errorsList []error
1318
Girish Gowdru0c588b22019-04-23 23:24:56 -04001319 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001320 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001321 dh.incrementActiveFlowRemoveCount(flow)
1322
Girish Kumar2ad402b2020-03-20 19:45:12 +00001323 logger.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001324 err := dh.flowMgr.RemoveFlow(ctx, flow)
1325 if err != nil {
1326 errorsList = append(errorsList, err)
1327 }
1328
1329 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001330 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301331
1332 for _, flow := range flows.ToAdd.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001333 logger.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001334 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1335 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001336 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1337 if err != nil {
1338 errorsList = append(errorsList, err)
1339 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301340 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001341 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001342 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001343 for _, flow := range flows.ToRemove.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001344 logger.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001345 // dh.flowMgr.RemoveFlow(flow)
1346 }
1347 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001348
Girish Gowdracefae192020-03-19 18:14:10 -07001349 // 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 +00001350 if groups != nil {
1351 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001352 err := dh.flowMgr.AddGroup(ctx, group)
1353 if err != nil {
1354 errorsList = append(errorsList, err)
1355 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001356 }
1357 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001358 err := dh.flowMgr.ModifyGroup(ctx, group)
1359 if err != nil {
1360 errorsList = append(errorsList, err)
1361 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001362 }
1363 if len(groups.ToRemove.Items) != 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001364 logger.Debug("Group delete operation is not supported for now")
Esin Karamanccb714b2019-11-29 15:02:06 +00001365 }
1366 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001367 if len(errorsList) > 0 {
1368 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1369 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001370 logger.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001371 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301372}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001373
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001374//DisableDevice disables the given device
1375//It marks the following for the given device:
1376//Device-Handler Admin-State : down
1377//Device Port-State: UNKNOWN
1378//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001379func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001380 /* On device disable ,admin state update has to be done prior sending request to agent since
1381 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001382 dh.lockDevice.Lock()
1383 dh.adminState = "down"
1384 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001385 if dh.Client != nil {
1386 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1387 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001388 dh.lockDevice.Lock()
1389 dh.adminState = "up"
1390 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001391 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001392 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001393 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001394 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001395 logger.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001396 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001397 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301398
1399 dh.discOnus = sync.Map{}
1400 dh.onus = sync.Map{}
1401
Thomas Lee S85f37312020-04-03 17:06:12 +05301402 //stopping the stats collector
1403 dh.stopCollector <- true
1404
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301405 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001406 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001407 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1408 for _, port := range cloned.Ports {
1409 if port.GetType() == voltha.Port_PON_OLT {
1410 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1411 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001412 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001413 }
1414 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001415 }
1416
Girish Kumar2ad402b2020-03-20 19:45:12 +00001417 logger.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001418 return nil
1419}
1420
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301421func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001422
1423 // Update onu state as unreachable in onu adapter
1424 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301425 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001426 //get the child device for the parent device
1427 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1428 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001429 logger.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001430 }
1431 if onuDevices != nil {
1432 for _, onuDevice := range onuDevices.Items {
1433 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1434 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1435 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001436 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001437 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1438 }
1439
1440 }
1441 }
1442
1443}
1444
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445//ReenableDevice re-enables the olt device after disable
1446//It marks the following for the given device:
1447//Device-Handler Admin-State : up
1448//Device Port-State: ACTIVE
1449//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001450func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001451 dh.lockDevice.Lock()
1452 dh.adminState = "up"
1453 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301454
1455 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1456 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301457 dh.lockDevice.Lock()
1458 dh.adminState = "down"
1459 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001460 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301461 }
1462 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001463 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001464
1465 cloned := proto.Clone(device).(*voltha.Device)
1466 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001467
kdarapu1afeceb2020-02-12 01:38:09 -05001468 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001469 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001470 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001471 //Update the device oper status as ACTIVE
1472 cloned.OperStatus = voltha.OperStatus_ACTIVE
1473 dh.device = cloned
1474
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001475 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301476 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001477 "device-id": device.Id,
1478 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001479 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001480 }
kesavand39e0aa32020-01-28 20:58:50 -05001481
Girish Kumar2ad402b2020-03-20 19:45:12 +00001482 logger.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001483
1484 return nil
1485}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001486
npujarec5762e2020-01-01 14:08:48 +05301487func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001488 var uniID uint32
1489 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301490 for _, port := range onu.UniPorts {
1491 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001492 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001493 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301494 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001495 logger.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001496 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001497 logger.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301498 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001499 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301500 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001501 }
npujarec5762e2020-01-01 14:08:48 +05301502 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001503 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301504 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001505 logger.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001506 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001507 logger.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301508 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001509 logger.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001510 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001511 logger.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301512 }
npujarec5762e2020-01-01 14:08:48 +05301513 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1514 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001515 logger.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301516 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001517 logger.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301518 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001519 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 +00001520 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001521 }
1522 return nil
1523}
1524
npujarec5762e2020-01-01 14:08:48 +05301525func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001526 nniUniID := -1
1527 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301528
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001529 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001530 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001531 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001532 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301533 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301534 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001535 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001536 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001537 logger.Debugw("NNI are ", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301538 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301539 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001540 logger.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301541 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301542 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301543 }
npujarec5762e2020-01-01 14:08:48 +05301544 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001545 }
npujarec5762e2020-01-01 14:08:48 +05301546 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001547 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301548 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001549 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001550}
1551
1552// 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 +05301553func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001554 logger.Debug("Function entry delete device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001555 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001556 if dh.adminState == "deleted" {
1557 dh.lockDevice.Unlock()
1558 return nil
1559 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001560 dh.adminState = "deleted"
1561 dh.lockDevice.Unlock()
1562 /* Clear the KV store data associated with the all the UNI ports
1563 This clears up flow data and also resource map data for various
1564 other pon resources like alloc_id and gemport_id
1565 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001566 go dh.cleanupDeviceResources(ctx)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001567 logger.Debug("Removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001568 // Stop the Stats collector
1569 dh.stopCollector <- true
1570 // stop the heartbeat check routine
1571 dh.stopHeartbeatCheck <- true
1572 //Reset the state
1573 if dh.Client != nil {
1574 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
1575 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
1576 }
1577 }
1578 cloned := proto.Clone(device).(*voltha.Device)
1579 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1580 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1581 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1582 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1583 "device-id": device.Id,
1584 "connect-status": cloned.ConnectStatus,
1585 "oper-status": cloned.OperStatus}, err).Log()
1586 }
1587 return nil
1588}
1589func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001590 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301591 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1592 var ponPort uint32
1593 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1594 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301595 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301596 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301597 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001598 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001599 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301600 }
1601 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301602 onuID := make([]uint32, 1)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001603 logger.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301604 if err = dh.clearUNIData(ctx, &onu); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001605 logger.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301606 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301607 // Clear flowids for gem cache.
1608 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301609 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301610 }
1611 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301612 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301613 }
npujarec5762e2020-01-01 14:08:48 +05301614 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301615 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301616 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301617 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001618 logger.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001619 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001620 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001621 /* Clear the flows from KV store associated with NNI port.
1622 There are mostly trap rules from NNI port (like LLDP)
1623 */
npujarec5762e2020-01-01 14:08:48 +05301624 if err := dh.clearNNIData(ctx); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001625 logger.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001626 }
A R Karthick1f85b802019-10-11 05:06:05 +00001627
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001628 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301629 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001630 }
A R Karthick1f85b802019-10-11 05:06:05 +00001631
Devmalya Paul495b94a2019-08-27 19:42:00 -04001632 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301633 dh.onus.Range(func(key interface{}, value interface{}) bool {
1634 dh.onus.Delete(key)
1635 return true
1636 })
1637
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001638 /*Delete discovered ONU map for the device*/
1639 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1640 dh.discOnus.Delete(key)
1641 return true
1642 })
1643
Devmalya Paul495b94a2019-08-27 19:42:00 -04001644 return nil
1645}
1646
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001647//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001648func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1649 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001650 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001651 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001652 logger.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001653 return nil
1654}
1655
David K. Bainbridge794735f2020-02-11 21:01:37 -08001656func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001657 logger.Debugw("Received packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001658 "packet-indication": *packetIn,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001659 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001660 "packet": hex.EncodeToString(packetIn.Pkt),
1661 })
npujarec5762e2020-01-01 14:08:48 +05301662 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001663 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001664 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001665 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001666 logger.Debugw("sending packet-in to core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001667 "logicalPortNum": logicalPortNum,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001668 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001669 "packet": hex.EncodeToString(packetIn.Pkt),
1670 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001671 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301672 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001673 "destination": "core",
1674 "source": dh.deviceType,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001675 "device-id": dh.device.Id,
1676 "packet": hex.EncodeToString(packetIn.Pkt),
1677 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001678 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001679 logger.Debugw("Success sending packet-in to core!", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001680 "packet": hex.EncodeToString(packetIn.Pkt),
1681 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001682 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001683 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001684}
1685
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001686// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301687func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001688 logger.Debugw("incoming-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001689 "deviceID": dh.deviceID,
1690 "egress_port_no": egressPortNo,
1691 "pkt-length": len(packet.Data),
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001692 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001693 "packet": hex.EncodeToString(packet.Data),
1694 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001695
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001696 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001697 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001698 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1699 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301700 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1701 // Do not packet-out lldp packets on uni port.
1702 // ONOS has no clue about uni/nni ports, it just packets out on all
1703 // available ports on the Logical Switch. It should not be interested
1704 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001705 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1706 "device-id": dh.device.Id,
1707 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301708 return nil
1709 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001710 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1711 if innerEthType == 0x8100 {
1712 // q-in-q 802.1ad or 802.1q double tagged packet.
1713 // slice out the outer tag.
1714 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001715 logger.Debugw("packet-now-single-tagged", log.Fields{
1716 "packetData": hex.EncodeToString(packet.Data),
1717 "device-id": dh.device.Id,
1718 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001719 }
1720 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001721 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1722 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001723 uniID := UniIDFromPortNum(uint32(egressPortNo))
1724
npujarec5762e2020-01-01 14:08:48 +05301725 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001726 if err != nil {
1727 // In this case the openolt agent will receive the gemPortID as 0.
1728 // The agent tries to retrieve the gemPortID in this case.
1729 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001730 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001731 "packet": hex.EncodeToString(packet.Data),
1732 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001733 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001734 }
1735
1736 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001737
Girish Kumar2ad402b2020-03-20 19:45:12 +00001738 logger.Debugw("sending-packet-to-onu", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001739 "egress_port_no": egressPortNo,
1740 "IntfId": intfID,
1741 "onuID": onuID,
1742 "uniID": uniID,
1743 "gemPortID": gemPortID,
1744 "packet": hex.EncodeToString(packet.Data),
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001745 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001746 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001747
npujarec5762e2020-01-01 14:08:48 +05301748 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301749 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001750 "source": "adapter",
1751 "destination": "onu",
1752 "egress-port-number": egressPortNo,
1753 "interface-id": intfID,
1754 "oni-id": onuID,
1755 "uni-id": uniID,
1756 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001757 "packet": hex.EncodeToString(packet.Data),
1758 "device-id": dh.device.Id,
1759 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001760 }
1761 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001762 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1763 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001764 return olterrors.NewErrInvalidValue(log.Fields{
1765 "egress-nni-port": egressPortNo,
1766 "device-id": dh.device.Id,
1767 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001768 }
1769 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001770
Girish Kumar2ad402b2020-03-20 19:45:12 +00001771 logger.Debugw("sending-packet-to-nni", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001772 "uplink_pkt": uplinkPkt,
1773 "packet": hex.EncodeToString(packet.Data),
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001774 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001775 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001776
npujarec5762e2020-01-01 14:08:48 +05301777 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001778 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1779 "packet": hex.EncodeToString(packet.Data),
1780 "device-id": dh.device.Id,
1781 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001782 }
1783 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001784 logger.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001785 "egress_port_no": egressPortNo,
1786 "egressPortType": egressPortType,
1787 "packet": hex.EncodeToString(packet.Data),
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001788 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001789 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001790 }
1791 return nil
1792}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001793
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001794func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1795 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001796}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301797
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001798func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301799 // start the heartbeat check towards the OLT.
1800 var timerCheck *time.Timer
1801
1802 for {
1803 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1804 select {
1805 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001806 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1807 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001808 logger.Error("Hearbeat failed")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301809 if timerCheck == nil {
1810 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001811 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301812 }
1813 } else {
1814 if timerCheck != nil {
1815 if timerCheck.Stop() {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001816 logger.Debug("We got hearbeat within the timeout")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301817 }
1818 timerCheck = nil
1819 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001820 logger.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301821 }
1822 cancel()
1823 case <-dh.stopHeartbeatCheck:
Girish Kumar2ad402b2020-03-20 19:45:12 +00001824 logger.Debug("Stopping heart beat check")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301825 return
1826 }
1827 }
1828}
1829
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001830func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1831 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1832 if err != nil || device == nil {
1833 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1834 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301835
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001836 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1837 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1838 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1839 }
1840 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1841 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1842 }
1843 go dh.cleanupDeviceResources(ctx)
1844
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001845 dh.lockDevice.RLock()
1846 // Stop the read indication only if it the routine is active
1847 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1848 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1849 // on next execution of the readIndication routine.
1850 if dh.isReadIndicationRoutineActive {
1851 dh.stopIndications <- true
1852 }
1853 dh.lockDevice.RUnlock()
1854
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001855 dh.transitionMap.Handle(ctx, DeviceInit)
1856
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301857 }
1858}
kesavand39e0aa32020-01-28 20:58:50 -05001859
1860// EnablePort to enable Pon interface
1861func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001862 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001863 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001864}
1865
1866// DisablePort to disable pon interface
1867func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001868 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001869 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001870}
1871
kdarapu1afeceb2020-02-12 01:38:09 -05001872//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1873func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301874 ctx := context.Background()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001875 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001876 if port.GetType() == voltha.Port_ETHERNET_NNI {
1877 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001878 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
kesavand39e0aa32020-01-28 20:58:50 -05001879 log.Fields{"Device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301880 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001881 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001882 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001883 }
1884 // fetch interfaceid from PortNo
1885 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1886 ponIntf := &oop.Interface{IntfId: ponID}
1887 var operStatus voltha.OperStatus_Types
1888 if enablePort {
1889 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301890 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001891
1892 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301893 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001894 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001895 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001896 }
1897 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001898 dh.activePorts.Store(ponID, true)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001899 logger.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001900 } else {
1901 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301902 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001903 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301904 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001905 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001906 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001907 }
1908 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001909 dh.activePorts.Store(ponID, false)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001910 logger.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001911 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001912 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 +05301913 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001914 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001915 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001916 }
1917 return nil
1918}
1919
kdarapu1afeceb2020-02-12 01:38:09 -05001920//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1921func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001922 cloned := proto.Clone(device).(*voltha.Device)
1923 // Disable the port and update the oper_port_status to core
1924 // if the Admin state of the port is disabled on reboot and re-enable device.
1925 for _, port := range cloned.Ports {
1926 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001927 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301928 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001929 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001930 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001931 }
1932 }
1933 }
1934 return nil
1935}
1936
1937//populateActivePorts to populate activePorts map
1938func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001939 logger.Info("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001940 for _, port := range device.Ports {
1941 if port.Type == voltha.Port_ETHERNET_NNI {
1942 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001943 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001944 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001945 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001946 }
1947 }
1948 if port.Type == voltha.Port_PON_OLT {
1949 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001950 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001951 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001952 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001953 }
1954 }
1955 }
1956}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001957
1958// ChildDeviceLost deletes ONU and clears pon resources related to it.
1959func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001960 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001961 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1962 onuKey := dh.formOnuKey(IntfID, onuID)
1963 onuDevice, ok := dh.onus.Load(onuKey)
1964 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301965 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001966 log.Fields{
1967 "device-id": dh.deviceID,
1968 "onu-id": onuID,
1969 "interface-id": IntfID}, nil).Log()
1970 }
1971 var sn *oop.SerialNumber
1972 var err error
1973 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301974 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001975 log.Fields{
1976 "devicer-id": dh.deviceID,
1977 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1978 }
1979 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1980 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301981 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001982 "device-id": dh.deviceID,
1983 "onu-id": onuID}, err).Log()
1984 }
1985 //clear PON resources associated with ONU
1986 var onuGemData []rsrcMgr.OnuGemInfo
Andrea Campanella668ea5f2020-03-31 13:51:06 +02001987 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[IntfID]; !ok {
1988 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001989 "device-id": dh.deviceID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02001990 "interface-id": IntfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001991 } else {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02001992 if err := onuMgr.GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
1993 logger.Warnw("failed-to-get-onu-info-for-pon-port ", log.Fields{
1994 "device-id": dh.deviceID,
1995 "interface-id": IntfID,
1996 "error": err})
1997 } else {
1998 for i, onu := range onuGemData {
1999 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
2000 logger.Debugw("onu-data ", log.Fields{"onu": onu})
2001 if err := dh.clearUNIData(ctx, &onu); err != nil {
2002 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
2003 "device-id": dh.deviceID,
2004 "onu-device": onu,
2005 "error": err})
2006 }
2007 // Clear flowids for gem cache.
2008 for _, gem := range onu.GemPorts {
2009 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
2010 }
2011 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
2012 err := onuMgr.AddOnuGemInfo(ctx, IntfID, onuGemData)
2013 if err != nil {
2014 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
2015 "interface-id": IntfID,
2016 "onu-device": onu,
2017 "onu-gem": onuGemData,
2018 "error": err})
2019 //Not returning error on cleanup.
2020 }
2021 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": IntfID, "onu-device": onu, "onugem": onuGemData})
2022 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
2023 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002024 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002025 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002026 }
2027 }
2028 dh.onus.Delete(onuKey)
2029 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2030 return nil
2031}
Girish Gowdracefae192020-03-19 18:14:10 -07002032
2033func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2034 for _, field := range flows.GetOfbFields(flow) {
2035 if field.Type == flows.IN_PORT {
2036 return field.GetPort()
2037 }
2038 }
2039 return InvalidPort
2040}
2041
2042func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2043 for _, action := range flows.GetActions(flow) {
2044 if action.Type == flows.OUTPUT {
2045 if out := action.GetOutput(); out != nil {
2046 return out.GetPort()
2047 }
2048 }
2049 }
2050 return InvalidPort
2051}
2052
2053func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2054 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002055 logger.Debugw("increment flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002056 if inPort != InvalidPort && outPort != InvalidPort {
2057 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2058 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002059 logger.Debugw("increment flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002060
2061 dh.lockDevice.Lock()
2062 defer dh.lockDevice.Unlock()
2063 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2064 if !ok {
2065 flowRemoveData = pendingFlowRemoveData{
2066 pendingFlowRemoveCount: 0,
2067 allFlowsRemoved: make(chan struct{}),
2068 }
2069 }
2070 flowRemoveData.pendingFlowRemoveCount++
2071 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2072
Girish Kumar2ad402b2020-03-20 19:45:12 +00002073 logger.Debugw("current flow remove count after increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002074 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2075 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2076 }
2077}
2078
2079func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2080 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002081 logger.Debugw("decrement flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002082 if inPort != InvalidPort && outPort != InvalidPort {
2083 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2084 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002085 logger.Debugw("decrement flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002086
2087 dh.lockDevice.Lock()
2088 defer dh.lockDevice.Unlock()
2089 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002090 logger.Fatalf("flow remove key not found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002091 } else {
2092 if val.pendingFlowRemoveCount > 0 {
2093 val.pendingFlowRemoveCount--
2094 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002095 logger.Debugw("current flow remove count after decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002096 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2097 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2098 // If all flow removes have finished, then close the channel to signal the receiver
2099 // to go ahead with flow adds.
2100 if val.pendingFlowRemoveCount == 0 {
2101 close(val.allFlowsRemoved)
2102 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2103 return
2104 }
2105 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2106 }
2107 }
2108}
2109
2110func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2111 var flowRemoveData pendingFlowRemoveData
2112 var ok bool
2113 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002114 logger.Debugw("wait for flow remove to finish for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002115 if inPort != InvalidPort && outPort != InvalidPort {
2116 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2117 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002118 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 -07002119
2120 dh.lockDevice.RLock()
2121 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002122 logger.Debugw("no pending flow to remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002123 dh.lockDevice.RUnlock()
2124 return
2125 }
2126 dh.lockDevice.RUnlock()
2127
2128 // Wait for all flow removes to finish first
2129 <-flowRemoveData.allFlowsRemoved
2130
Girish Kumar2ad402b2020-03-20 19:45:12 +00002131 logger.Debugw("all flows cleared, handling flow add now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002132 }
2133}
2134
2135func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2136 inPort := getInPortFromFlow(flow)
2137 outPort := getOutPortFromFlow(flow)
2138
2139 if inPort == InvalidPort || outPort == InvalidPort {
2140 return inPort, outPort
2141 }
2142
2143 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2144 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2145 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2146 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2147 return uniPort, outPort
2148 }
2149 }
2150 } else {
2151 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2152 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2153 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2154 return inPort, uniPort
2155 }
2156 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2157 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2158 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2159 return uniPort, outPort
2160 }
2161 }
2162 }
2163
2164 return InvalidPort, InvalidPort
2165}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002166
2167func extractOmciTransactionID(omciPkt []byte) uint16 {
2168 if len(omciPkt) > 3 {
2169 d := omciPkt[0:2]
2170 transid := binary.BigEndian.Uint16(d)
2171 return transid
2172 }
2173 return 0
2174}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002175
2176// StoreOnuDevice stores the onu parameters to the local cache.
2177func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2178 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2179 dh.onus.Store(onuKey, onuDevice)
2180}