blob: 74e1f301b341de779ca51303232ae712fc180eb5 [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()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000514 logger.Infow("Received pakcet indication ", log.Fields{"PktInd": pktInd})
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 {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400535 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530536 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400537 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000538 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400539 }
540 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530541}
542
543// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530544func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700545 dh.lockDevice.Lock()
546 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000547 logger.Debug("do-state-down-start")
Girish Gowdrud4245152019-05-10 00:47:31 -0400548
npujarec5762e2020-01-01 14:08:48 +0530549 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400550 if err != nil || device == nil {
551 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000552 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400553 }
554
555 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400556
557 //Update the device oper state and connection status
558 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400559 dh.device = cloned
560
David K. Bainbridge794735f2020-02-11 21:01:37 -0800561 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000562 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400563 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400564
565 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530566 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400567 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000568 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400569 }
570 for _, onuDevice := range onuDevices.Items {
571
572 // Update onu state as down in onu adapter
573 onuInd := oop.OnuIndication{}
574 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800575 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700576 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800577 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530578 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800579 "source": "openolt",
580 "onu-indicator": onuInd,
581 "device-type": onuDevice.Type,
582 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700583 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700584 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400585 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700586 /* Discovered ONUs entries need to be cleared , since after OLT
587 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530588 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000589 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700590 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530591}
592
593// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530594func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400595 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800596 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530597 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800598 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000599 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400600 }
601 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530602}
603
604// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530605func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400606 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530607 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400608 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530609}
610
611// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530612func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000613 logger.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400614
615 // Case where OLT is disabled and then rebooted.
616 if dh.adminState == "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000617 logger.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530618 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400619 if err != nil || device == nil {
620 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530621 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400622 }
623
624 cloned := proto.Clone(device).(*voltha.Device)
625 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
626 cloned.OperStatus = voltha.OperStatus_UNKNOWN
627 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530628 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530629 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400630 }
631
Chaitrashree G S44124192019-08-07 20:21:36 -0400632 // 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 +0530633 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400634 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530635 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400636 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400637 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
638 // all the modules initialized and ready to handle incoming ONUs.
639
640 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
641 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
642 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400643
644 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800645 go func() {
646 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530647 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800648 }
649 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400650 return nil
651 }
652
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700653 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400654 if err != nil || device == nil {
655 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000656 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400657 }
kesavand39e0aa32020-01-28 20:58:50 -0500658 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500659 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000660 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400661 }
662
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400663 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
664 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400665 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530666
cuilin20187b2a8c32019-03-26 19:52:28 -0700667 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800668 go func() {
669 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530670 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 }
672 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700673 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530674}
675
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400676func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
677 deviceInfo, err := dh.populateDeviceInfo()
678
679 if err != nil {
680 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
681 }
682 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
683 // Instantiate resource manager
684 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
685 return olterrors.ErrResourceManagerInstantiating
686 }
687
688 // Instantiate flow manager
689 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
690 return olterrors.ErrResourceManagerInstantiating
691
692 }
693 /* TODO: Instantiate Alarm , stats , BW managers */
694 /* Instantiating Event Manager to handle Alarms and KPIs */
695 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
696
697 // Stats config for new device
698 dh.portStats = NewOpenOltStatsMgr(dh)
699
700 return nil
701
702}
703
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400704func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
705 var err error
706 var deviceInfo *oop.DeviceInfo
707
708 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
709
710 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000711 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400712 }
713 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000714 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400715 }
716
Girish Kumar2ad402b2020-03-20 19:45:12 +0000717 logger.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400718 dh.device.Root = true
719 dh.device.Vendor = deviceInfo.Vendor
720 dh.device.Model = deviceInfo.Model
721 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
722 dh.device.HardwareVersion = deviceInfo.HardwareVersion
723 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
724
725 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000726 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400727 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
728 genmac, err := generateMacFromHost(host)
729 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000730 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400731 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000732 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400733 dh.device.MacAddress = genmac
734 } else {
735 dh.device.MacAddress = deviceInfo.DeviceId
736 }
737
738 // Synchronous call to update device - this method is run in its own go routine
739 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000740 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400741 }
742
743 return deviceInfo, nil
744}
745
Naga Manjunath7615e552019-10-11 22:35:47 +0530746func startCollector(dh *DeviceHandler) {
747 // Initial delay for OLT initialization
748 time.Sleep(1 * time.Minute)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000749 logger.Debugf("Starting-Collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530750 context := make(map[string]string)
751 for {
752 select {
753 case <-dh.stopCollector:
Girish Kumar2ad402b2020-03-20 19:45:12 +0000754 logger.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
Naga Manjunath7615e552019-10-11 22:35:47 +0530755 return
756 default:
757 freq := dh.metrics.ToPmConfigs().DefaultFreq
758 time.Sleep(time.Duration(freq) * time.Second)
759 context["oltid"] = dh.deviceID
760 context["devicetype"] = dh.deviceType
761 // NNI Stats
762 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
Girish Kumar2ad402b2020-03-20 19:45:12 +0000763 logger.Debugf("Collect-NNI-Metrics %v", cmnni)
Naga Manjunath7615e552019-10-11 22:35:47 +0530764 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000765 logger.Debugf("Publish-NNI-Metrics")
Naga Manjunath7615e552019-10-11 22:35:47 +0530766 // PON Stats
767 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500768 for i := uint32(0); i < NumPonPORTS; i++ {
769 if val, ok := dh.activePorts.Load(i); ok && val == true {
770 cmpon := dh.portStats.collectPONMetrics(i)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000771 logger.Debugf("Collect-PON-Metrics %v", cmpon)
Naga Manjunath7615e552019-10-11 22:35:47 +0530772
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
792 go startCollector(dh)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400793 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530794}
795
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700796//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530797func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700798 return &ic.SwitchCapability{
799 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530800 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700801 HwDesc: "open_pon",
802 SwDesc: "open_pon",
803 SerialNum: dh.device.SerialNumber,
804 },
805 SwitchFeatures: &of.OfpSwitchFeatures{
806 NBuffers: 256,
807 NTables: 2,
808 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
809 of.OfpCapabilities_OFPC_TABLE_STATS |
810 of.OfpCapabilities_OFPC_PORT_STATS |
811 of.OfpCapabilities_OFPC_GROUP_STATS),
812 },
813 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530814}
815
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700816//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530817func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700818 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700819 return &ic.PortCapability{
820 Port: &voltha.LogicalPort{
821 OfpPort: &of.OfpPort{
822 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
823 Config: 0,
824 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700825 Curr: capacity,
826 Advertised: capacity,
827 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700828 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
829 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
830 },
831 DeviceId: dh.device.Id,
832 DevicePortNo: uint32(portNo),
833 },
834 }, nil
835}
836
David K. Bainbridge794735f2020-02-11 21:01:37 -0800837func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000838 logger.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700839 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700840 var deviceID string
841 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700842
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400843 transid := extractOmciTransactionID(omciInd.Pkt)
844 logger.Debugw("recv-omci-msg", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId,
845 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
846
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700847 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530848
849 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
850
Girish Kumar2ad402b2020-03-20 19:45:12 +0000851 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 -0700852 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700853 kwargs := make(map[string]interface{})
854 kwargs["onu_id"] = omciInd.OnuId
855 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700856
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700857 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
858 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530859 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800860 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000861 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700862 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700863 deviceType = onuDevice.Type
864 deviceID = onuDevice.Id
865 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
866 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530867 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700868 } else {
869 //found in cache
Girish Kumar2ad402b2020-03-20 19:45:12 +0000870 logger.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530871 deviceType = onuInCache.(*OnuDevice).deviceType
872 deviceID = onuInCache.(*OnuDevice).deviceID
873 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700874 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700875
876 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800877 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700878 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800879 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530880 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800881 "source": dh.deviceType,
882 "destination": deviceType,
883 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000884 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700885 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800886 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530887}
888
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700889//ProcessInterAdapterMessage sends the proxied messages to the target device
890// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
891// is meant, and then send the unmarshalled omci message to this onu
892func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000893 logger.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700894 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700895 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700896 fromTopic := msg.Header.FromTopic
897 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700898 toDeviceID := msg.Header.ToDeviceId
899 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700900
Girish Kumar2ad402b2020-03-20 19:45:12 +0000901 logger.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700902
903 msgBody := msg.GetBody()
904
905 omciMsg := &ic.InterAdapterOmciMessage{}
906 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000907 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700908 }
909
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700910 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700911 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
912 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530913 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800914 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000915 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700916 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000917 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 -0800918 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530919 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800920 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000921 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800922 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700923 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000924 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 -0800925 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530926 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800927 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000928 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800929 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700930 }
931
932 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000933 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700934 }
935 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530936}
937
David K. Bainbridge794735f2020-02-11 21:01:37 -0800938func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700939 var intfID uint32
940 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000941 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700942 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700943 intfID = onuDevice.ProxyAddress.GetChannelId()
944 onuID = onuDevice.ProxyAddress.GetOnuId()
945 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700946 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700947 intfID = omciMsg.GetProxyAddress().GetChannelId()
948 onuID = omciMsg.GetProxyAddress().GetOnuId()
949 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700950 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700951 if connectStatus != voltha.ConnectStatus_REACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000952 logger.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800953
Thomas Lee S94109f12020-03-03 16:39:29 +0530954 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800955 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000956 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700957 }
958
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400959 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
960 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700961 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400962 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
963 hex.Encode(hexPkt, omciMsg.Message)
964 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
965
966 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
967 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
968 transid := extractOmciTransactionID(omciMsg.Message)
969 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
970 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700971
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700972 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
973 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530974 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800975 "interface-id": intfID,
976 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000977 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700978 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800979 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700980}
981
David K. Bainbridge794735f2020-02-11 21:01:37 -0800982func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000983 logger.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
Andrea Campanellab83b39d2020-03-30 11:41:16 +0200984 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
985 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
986 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700987 // TODO: need resource manager
988 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700989 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530990 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400991 st, _ := status.FromError(err)
992 if st.Code() == codes.AlreadyExists {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000993 logger.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400994 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000995 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400996 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700997 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000998 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
cuilin20187b2a8c32019-03-26 19:52:28 -0700999 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001000 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001001}
1002
David K. Bainbridge794735f2020-02-11 21:01:37 -08001003func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001004
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001005 channelID := onuDiscInd.GetIntfId()
1006 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001007
Girish Kumar2ad402b2020-03-20 19:45:12 +00001008 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301009
cuilin20187b2a8c32019-03-26 19:52:28 -07001010 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001011 if sn != "" {
1012 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001013 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001014 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001015 }
1016
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301017 var alarmInd oop.OnuAlarmIndication
1018 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001019 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301020
1021 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1022 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1023 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1024 OnuLosRaise event sent for it */
1025 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1026 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1027 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001028 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301029 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1030 "currentIntfId": onuDiscInd.GetIntfId()})
1031 // TODO:: Should we need to ignore raising OnuLosClear event
1032 // when onu connected to different PON?
1033 }
1034 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1035 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1036 alarmInd.LosStatus = statusCheckOff
1037 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1038 }
1039 return true
1040 })
1041
Girish Kumar2ad402b2020-03-20 19:45:12 +00001042 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001044 }
1045
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001046 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001047
1048 // check the ONU is already know to the OLT
1049 // NOTE the second time the ONU is discovered this should return a device
1050 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1051
1052 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001053 logger.Warnw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001054 if e, ok := status.FromError(err); ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001055 logger.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001056 switch e.Code() {
1057 case codes.Internal:
1058 // this probably means NOT FOUND, so just create a new device
1059 onuDevice = nil
1060 case codes.DeadlineExceeded:
1061 // if the call times out, cleanup and exit
1062 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001063 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001064 }
1065 }
1066 }
1067
1068 if onuDevice == nil {
1069 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Girish Kumar2ad402b2020-03-20 19:45:12 +00001070 logger.Infow("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001071 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001072 ponintfid := onuDiscInd.GetIntfId()
1073 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301074 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001075 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001076
Girish Kumar2ad402b2020-03-20 19:45:12 +00001077 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001078
1079 if err != nil {
1080 // if we can't create an ID in resource manager,
1081 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001082 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001083 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001084 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001085 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001086 }
1087
1088 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1089 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001090 dh.discOnus.Delete(sn)
1091 dh.resourceMgr.FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301092 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001093 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001094 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001095 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001096 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Girish Kumar2ad402b2020-03-20 19:45:12 +00001097 logger.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001098 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001099
1100 // we can now use the existing ONU Id
1101 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001102 //Insert the ONU into cache to use in OnuIndication.
1103 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001104 logger.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
Matteo Scandolo945e4012019-12-12 14:16:11 -08001105 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001106 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001107
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301108 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301109 dh.onus.Store(onuKey, onuDev)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001110 logger.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001111
David K. Bainbridge794735f2020-02-11 21:01:37 -08001112 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301113 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001114 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001115 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001116 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001117 logger.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001118 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301119 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001120 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001121 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001122 }
1123 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001124}
1125
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001127 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1128
1129 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001130 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001131 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001133 foundInCache := false
Girish Kumar2ad402b2020-03-20 19:45:12 +00001134 logger.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
Scott Baker7eb0a932019-07-26 10:33:22 -07001135 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001136 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301137
David K. Bainbridge794735f2020-02-11 21:01:37 -08001138 errFields := log.Fields{"device-id": dh.device.Id}
1139
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301140 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1141
Mahir Gunyele77977b2019-06-27 05:36:22 -07001142 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1143 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1145 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001146 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001147 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1148 if serialNumber != "" {
1149 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001150 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001151 } else {
1152 kwargs["onu_id"] = onuInd.OnuId
1153 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001154 errFields["onu-id"] = onuInd.OnuId
1155 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001156 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001158 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001159
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001161 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001162 }
1163
David K. Bainbridge794735f2020-02-11 21:01:37 -08001164 if onuDevice.ParentPortNo != ponPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001165 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001166 "previousIntfId": onuDevice.ParentPortNo,
1167 "currentIntfId": ponPort})
1168 }
1169
1170 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001171 logger.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001172 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1173 "received_onu_id": onuInd.OnuId})
1174 }
1175 if !foundInCache {
1176 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1177
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301178 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001179
1180 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001181 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001182 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 }
1184 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001185}
1186
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001187func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301188 ctx := context.TODO()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001189 logger.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001190 if onuInd.AdminState == "down" {
1191 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1192 if onuInd.OperState != "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001193 logger.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001194 onuInd.OperState = "down"
1195 }
1196 }
1197
David K. Bainbridge794735f2020-02-11 21:01:37 -08001198 switch onuInd.OperState {
1199 case "down":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001200 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001201 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301202 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001203 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1204 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301205 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001206 "onu-indicator": onuInd,
1207 "source": "openolt",
1208 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001209 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001210 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001211 case "up":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001212 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Matt Jeanneret53539512019-07-20 14:47:02 -04001213 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301214 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001215 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1216 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301217 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 "onu-indicator": onuInd,
1219 "source": "openolt",
1220 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001221 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001222 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001223 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001224 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001225 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001226 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001227}
1228
cuilin20187b2a8c32019-03-26 19:52:28 -07001229func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1230 if serialNum != nil {
1231 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001232 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001233 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001234}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001235func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1236 decodedStr, err := hex.DecodeString(serialNum[4:])
1237 if err != nil {
1238 return nil, err
1239 }
1240 return &oop.SerialNumber{
1241 VendorId: []byte(serialNum[:4]),
1242 VendorSpecific: []byte(decodedStr),
1243 }, nil
1244}
cuilin20187b2a8c32019-03-26 19:52:28 -07001245
1246func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1247 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001248 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001249 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1250 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1251 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1252 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1253 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1254 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1255 return tmp
1256}
1257
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001258//UpdateFlowsBulk upates the bulk flow
1259func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301260 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001261}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001262
1263//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001265 logger.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001266 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001267 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001268 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001269 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001270 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001271 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001273 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001274 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001275 logger.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001276 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301277}
1278
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001279// SendPacketInToCore sends packet-in to core
1280// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1281// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001283 logger.Debugw("send-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001284 "port": logicalPort,
1285 "packet": hex.EncodeToString(packetPayload),
1286 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001287 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301288 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001289 "source": "adapter",
1290 "destination": "core",
1291 "device-id": dh.device.Id,
1292 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001293 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001294 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001295 logger.Debugw("Sent packet-in to core successfully", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001296 "packet": hex.EncodeToString(packetPayload),
1297 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001299}
1300
A R Karthick1f85b802019-10-11 05:06:05 +00001301// AddUniPortToOnu adds the uni port to the onu device
1302func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1303 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301304
1305 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001306 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301307 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1308 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001309 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001310 }
1311 }
1312}
1313
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001314//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301315func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001316 logger.Debugw("Received-incremental-flowupdate-in-device-handler", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001317
1318 var errorsList []error
1319
Girish Gowdru0c588b22019-04-23 23:24:56 -04001320 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001321 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001322 dh.incrementActiveFlowRemoveCount(flow)
1323
Girish Kumar2ad402b2020-03-20 19:45:12 +00001324 logger.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001325 err := dh.flowMgr.RemoveFlow(ctx, flow)
1326 if err != nil {
1327 errorsList = append(errorsList, err)
1328 }
1329
1330 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001331 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301332
1333 for _, flow := range flows.ToAdd.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001334 logger.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001335 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1336 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001337 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1338 if err != nil {
1339 errorsList = append(errorsList, err)
1340 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301341 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001342 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001343 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001344 for _, flow := range flows.ToRemove.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001345 logger.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001346 // dh.flowMgr.RemoveFlow(flow)
1347 }
1348 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001349
Girish Gowdracefae192020-03-19 18:14:10 -07001350 // Whether we need to synchronize multicast group adds and modifies like flow add and delete needs to be investigated
Esin Karamanccb714b2019-11-29 15:02:06 +00001351 if groups != nil {
1352 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001353 err := dh.flowMgr.AddGroup(ctx, group)
1354 if err != nil {
1355 errorsList = append(errorsList, err)
1356 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001357 }
1358 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001359 err := dh.flowMgr.ModifyGroup(ctx, group)
1360 if err != nil {
1361 errorsList = append(errorsList, err)
1362 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001363 }
1364 if len(groups.ToRemove.Items) != 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001365 logger.Debug("Group delete operation is not supported for now")
Esin Karamanccb714b2019-11-29 15:02:06 +00001366 }
1367 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001368 if len(errorsList) > 0 {
1369 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1370 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001371 logger.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001372 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301373}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001374
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375//DisableDevice disables the given device
1376//It marks the following for the given device:
1377//Device-Handler Admin-State : down
1378//Device Port-State: UNKNOWN
1379//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001380func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001381 /* On device disable ,admin state update has to be done prior sending request to agent since
1382 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001383 dh.lockDevice.Lock()
1384 dh.adminState = "down"
1385 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001386 if dh.Client != nil {
1387 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1388 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001389 dh.lockDevice.Lock()
1390 dh.adminState = "up"
1391 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001392 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001393 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001394 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001395 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001396 logger.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001397 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001398 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301399
1400 dh.discOnus = sync.Map{}
1401 dh.onus = sync.Map{}
1402
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301403 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001404 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001405 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1406 for _, port := range cloned.Ports {
1407 if port.GetType() == voltha.Port_PON_OLT {
1408 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1409 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001410 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001411 }
1412 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001413 }
1414
Girish Kumar2ad402b2020-03-20 19:45:12 +00001415 logger.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001416 return nil
1417}
1418
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301419func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001420
1421 // Update onu state as unreachable in onu adapter
1422 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301423 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001424 //get the child device for the parent device
1425 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1426 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001427 logger.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001428 }
1429 if onuDevices != nil {
1430 for _, onuDevice := range onuDevices.Items {
1431 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1432 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1433 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001434 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001435 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1436 }
1437
1438 }
1439 }
1440
1441}
1442
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001443//ReenableDevice re-enables the olt device after disable
1444//It marks the following for the given device:
1445//Device-Handler Admin-State : up
1446//Device Port-State: ACTIVE
1447//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001448func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001449 dh.lockDevice.Lock()
1450 dh.adminState = "up"
1451 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301452
1453 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1454 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301455 dh.lockDevice.Lock()
1456 dh.adminState = "down"
1457 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001458 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301459 }
1460 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001461 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001462
1463 cloned := proto.Clone(device).(*voltha.Device)
1464 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001465
kdarapu1afeceb2020-02-12 01:38:09 -05001466 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001467 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001468 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001469 //Update the device oper status as ACTIVE
1470 cloned.OperStatus = voltha.OperStatus_ACTIVE
1471 dh.device = cloned
1472
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001473 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301474 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001475 "device-id": device.Id,
1476 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001477 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001478 }
kesavand39e0aa32020-01-28 20:58:50 -05001479
Girish Kumar2ad402b2020-03-20 19:45:12 +00001480 logger.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001481
1482 return nil
1483}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001484
npujarec5762e2020-01-01 14:08:48 +05301485func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001486 var uniID uint32
1487 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301488 for _, port := range onu.UniPorts {
1489 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001490 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001491 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301492 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001493 logger.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001494 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001495 logger.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301496 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001497 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301498 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001499 }
npujarec5762e2020-01-01 14:08:48 +05301500 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001501 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301502 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001503 logger.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001504 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001505 logger.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301506 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001507 logger.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001508 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001509 logger.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301510 }
npujarec5762e2020-01-01 14:08:48 +05301511 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1512 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001513 logger.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301514 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001515 logger.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301516 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001517 logger.Debugw("Failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001518 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001519 }
1520 return nil
1521}
1522
npujarec5762e2020-01-01 14:08:48 +05301523func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001524 nniUniID := -1
1525 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301526
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001527 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001528 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001529 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001530 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301531 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301532 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001533 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001534 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001535 logger.Debugw("NNI are ", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301536 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301537 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001538 logger.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301539 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301540 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301541 }
npujarec5762e2020-01-01 14:08:48 +05301542 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001543 }
npujarec5762e2020-01-01 14:08:48 +05301544 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001545 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301546 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001547 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001548}
1549
1550// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
npujarec5762e2020-01-01 14:08:48 +05301551func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001552 logger.Debug("Function entry delete device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001553 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001554 if dh.adminState == "deleted" {
1555 dh.lockDevice.Unlock()
1556 return nil
1557 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001558 dh.adminState = "deleted"
1559 dh.lockDevice.Unlock()
1560 /* Clear the KV store data associated with the all the UNI ports
1561 This clears up flow data and also resource map data for various
1562 other pon resources like alloc_id and gemport_id
1563 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001564 go dh.cleanupDeviceResources(ctx)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001565 logger.Debug("Removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001566 // Stop the Stats collector
1567 dh.stopCollector <- true
1568 // stop the heartbeat check routine
1569 dh.stopHeartbeatCheck <- true
1570 //Reset the state
1571 if dh.Client != nil {
1572 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
1573 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
1574 }
1575 }
1576 cloned := proto.Clone(device).(*voltha.Device)
1577 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1578 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1579 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1580 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1581 "device-id": device.Id,
1582 "connect-status": cloned.ConnectStatus,
1583 "oper-status": cloned.OperStatus}, err).Log()
1584 }
1585 return nil
1586}
1587func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001588 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301589 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1590 var ponPort uint32
1591 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1592 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301593 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301594 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301595 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001596 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001597 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301598 }
1599 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301600 onuID := make([]uint32, 1)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001601 logger.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301602 if err = dh.clearUNIData(ctx, &onu); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001603 logger.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301604 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301605 // Clear flowids for gem cache.
1606 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301607 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301608 }
1609 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301610 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301611 }
npujarec5762e2020-01-01 14:08:48 +05301612 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301613 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301614 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301615 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001616 logger.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001617 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001618 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001619 /* Clear the flows from KV store associated with NNI port.
1620 There are mostly trap rules from NNI port (like LLDP)
1621 */
npujarec5762e2020-01-01 14:08:48 +05301622 if err := dh.clearNNIData(ctx); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001623 logger.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001624 }
A R Karthick1f85b802019-10-11 05:06:05 +00001625
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001626 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301627 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001628 }
A R Karthick1f85b802019-10-11 05:06:05 +00001629
Devmalya Paul495b94a2019-08-27 19:42:00 -04001630 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301631 dh.onus.Range(func(key interface{}, value interface{}) bool {
1632 dh.onus.Delete(key)
1633 return true
1634 })
1635
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001636 /*Delete discovered ONU map for the device*/
1637 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1638 dh.discOnus.Delete(key)
1639 return true
1640 })
1641
Devmalya Paul495b94a2019-08-27 19:42:00 -04001642 return nil
1643}
1644
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001645//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001646func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1647 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001648 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001649 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001650 logger.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001651 return nil
1652}
1653
David K. Bainbridge794735f2020-02-11 21:01:37 -08001654func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001655 logger.Debugw("Received packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001656 "packet-indication": *packetIn,
1657 "packet": hex.EncodeToString(packetIn.Pkt),
1658 })
npujarec5762e2020-01-01 14:08:48 +05301659 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001660 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001661 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001662 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001663 logger.Debugw("sending packet-in to core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001664 "logicalPortNum": logicalPortNum,
1665 "packet": hex.EncodeToString(packetIn.Pkt),
1666 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001667 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301668 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001669 "destination": "core",
1670 "source": dh.deviceType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001671 "packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001672 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001673 logger.Debugw("Success sending packet-in to core!", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001674 "packet": hex.EncodeToString(packetIn.Pkt),
1675 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001676 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001677}
1678
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001679// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301680func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001681 logger.Debugw("incoming-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001682 "deviceID": dh.deviceID,
1683 "egress_port_no": egressPortNo,
1684 "pkt-length": len(packet.Data),
1685 "packet": hex.EncodeToString(packet.Data),
1686 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001687
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001688 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001689 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001690 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1691 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301692 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1693 // Do not packet-out lldp packets on uni port.
1694 // ONOS has no clue about uni/nni ports, it just packets out on all
1695 // available ports on the Logical Switch. It should not be interested
1696 // in the UNI links.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001697 logger.Debug("dropping-lldp-packet-out-on-uni")
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301698 return nil
1699 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001700 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1701 if innerEthType == 0x8100 {
1702 // q-in-q 802.1ad or 802.1q double tagged packet.
1703 // slice out the outer tag.
1704 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001705 logger.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001706 }
1707 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001708 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1709 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001710 uniID := UniIDFromPortNum(uint32(egressPortNo))
1711
npujarec5762e2020-01-01 14:08:48 +05301712 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001713 if err != nil {
1714 // In this case the openolt agent will receive the gemPortID as 0.
1715 // The agent tries to retrieve the gemPortID in this case.
1716 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001717 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001718 "packet": hex.EncodeToString(packet.Data),
1719 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001720 }
1721
1722 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001723
Girish Kumar2ad402b2020-03-20 19:45:12 +00001724 logger.Debugw("sending-packet-to-onu", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001725 "egress_port_no": egressPortNo,
1726 "IntfId": intfID,
1727 "onuID": onuID,
1728 "uniID": uniID,
1729 "gemPortID": gemPortID,
1730 "packet": hex.EncodeToString(packet.Data),
1731 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001732
npujarec5762e2020-01-01 14:08:48 +05301733 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301734 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001735 "source": "adapter",
1736 "destination": "onu",
1737 "egress-port-number": egressPortNo,
1738 "interface-id": intfID,
1739 "oni-id": onuID,
1740 "uni-id": uniID,
1741 "gem-port-id": gemPortID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001742 "packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001743 }
1744 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001745 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1746 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001747 return olterrors.NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001748 }
1749 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001750
Girish Kumar2ad402b2020-03-20 19:45:12 +00001751 logger.Debugw("sending-packet-to-nni", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001752 "uplink_pkt": uplinkPkt,
1753 "packet": hex.EncodeToString(packet.Data),
1754 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001755
npujarec5762e2020-01-01 14:08:48 +05301756 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001757 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001758 }
1759 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001760 logger.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001761 "egress_port_no": egressPortNo,
1762 "egressPortType": egressPortType,
1763 "packet": hex.EncodeToString(packet.Data),
1764 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001765 }
1766 return nil
1767}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001768
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001769func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1770 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001771}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301772
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001773func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301774 // start the heartbeat check towards the OLT.
1775 var timerCheck *time.Timer
1776
1777 for {
1778 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1779 select {
1780 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001781 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1782 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001783 logger.Error("Hearbeat failed")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301784 if timerCheck == nil {
1785 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001786 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301787 }
1788 } else {
1789 if timerCheck != nil {
1790 if timerCheck.Stop() {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001791 logger.Debug("We got hearbeat within the timeout")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301792 }
1793 timerCheck = nil
1794 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001795 logger.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301796 }
1797 cancel()
1798 case <-dh.stopHeartbeatCheck:
Girish Kumar2ad402b2020-03-20 19:45:12 +00001799 logger.Debug("Stopping heart beat check")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301800 return
1801 }
1802 }
1803}
1804
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001805func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1806 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1807 if err != nil || device == nil {
1808 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1809 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301810
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001811 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1812 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1813 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1814 }
1815 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1816 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1817 }
1818 go dh.cleanupDeviceResources(ctx)
1819
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001820 dh.lockDevice.RLock()
1821 // Stop the read indication only if it the routine is active
1822 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1823 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1824 // on next execution of the readIndication routine.
1825 if dh.isReadIndicationRoutineActive {
1826 dh.stopIndications <- true
1827 }
1828 dh.lockDevice.RUnlock()
1829
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001830 dh.transitionMap.Handle(ctx, DeviceInit)
1831
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301832 }
1833}
kesavand39e0aa32020-01-28 20:58:50 -05001834
1835// EnablePort to enable Pon interface
1836func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001837 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001838 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001839}
1840
1841// DisablePort to disable pon interface
1842func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001843 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001844 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001845}
1846
kdarapu1afeceb2020-02-12 01:38:09 -05001847//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1848func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301849 ctx := context.Background()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001850 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001851 if port.GetType() == voltha.Port_ETHERNET_NNI {
1852 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001853 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
kesavand39e0aa32020-01-28 20:58:50 -05001854 log.Fields{"Device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301855 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001856 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001857 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001858 }
1859 // fetch interfaceid from PortNo
1860 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1861 ponIntf := &oop.Interface{IntfId: ponID}
1862 var operStatus voltha.OperStatus_Types
1863 if enablePort {
1864 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301865 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001866
1867 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301868 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001869 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001870 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001871 }
1872 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001873 dh.activePorts.Store(ponID, true)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001874 logger.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001875 } else {
1876 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301877 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001878 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301879 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001880 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001881 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001882 }
1883 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001884 dh.activePorts.Store(ponID, false)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001885 logger.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001886 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001887 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 +05301888 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001889 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001890 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001891 }
1892 return nil
1893}
1894
kdarapu1afeceb2020-02-12 01:38:09 -05001895//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1896func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001897 cloned := proto.Clone(device).(*voltha.Device)
1898 // Disable the port and update the oper_port_status to core
1899 // if the Admin state of the port is disabled on reboot and re-enable device.
1900 for _, port := range cloned.Ports {
1901 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001902 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301903 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001904 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001905 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001906 }
1907 }
1908 }
1909 return nil
1910}
1911
1912//populateActivePorts to populate activePorts map
1913func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001914 logger.Info("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001915 for _, port := range device.Ports {
1916 if port.Type == voltha.Port_ETHERNET_NNI {
1917 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001918 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001919 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001920 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001921 }
1922 }
1923 if port.Type == voltha.Port_PON_OLT {
1924 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001925 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001926 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001927 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001928 }
1929 }
1930 }
1931}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001932
1933// ChildDeviceLost deletes ONU and clears pon resources related to it.
1934func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001935 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001936 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1937 onuKey := dh.formOnuKey(IntfID, onuID)
1938 onuDevice, ok := dh.onus.Load(onuKey)
1939 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301940 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001941 log.Fields{
1942 "device-id": dh.deviceID,
1943 "onu-id": onuID,
1944 "interface-id": IntfID}, nil).Log()
1945 }
1946 var sn *oop.SerialNumber
1947 var err error
1948 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301949 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001950 log.Fields{
1951 "devicer-id": dh.deviceID,
1952 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1953 }
1954 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1955 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301956 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001957 "device-id": dh.deviceID,
1958 "onu-id": onuID}, err).Log()
1959 }
1960 //clear PON resources associated with ONU
1961 var onuGemData []rsrcMgr.OnuGemInfo
Andrea Campanella668ea5f2020-03-31 13:51:06 +02001962 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[IntfID]; !ok {
1963 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001964 "device-id": dh.deviceID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02001965 "interface-id": IntfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001966 } else {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02001967 if err := onuMgr.GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
1968 logger.Warnw("failed-to-get-onu-info-for-pon-port ", log.Fields{
1969 "device-id": dh.deviceID,
1970 "interface-id": IntfID,
1971 "error": err})
1972 } else {
1973 for i, onu := range onuGemData {
1974 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
1975 logger.Debugw("onu-data ", log.Fields{"onu": onu})
1976 if err := dh.clearUNIData(ctx, &onu); err != nil {
1977 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
1978 "device-id": dh.deviceID,
1979 "onu-device": onu,
1980 "error": err})
1981 }
1982 // Clear flowids for gem cache.
1983 for _, gem := range onu.GemPorts {
1984 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
1985 }
1986 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
1987 err := onuMgr.AddOnuGemInfo(ctx, IntfID, onuGemData)
1988 if err != nil {
1989 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
1990 "interface-id": IntfID,
1991 "onu-device": onu,
1992 "onu-gem": onuGemData,
1993 "error": err})
1994 //Not returning error on cleanup.
1995 }
1996 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": IntfID, "onu-device": onu, "onugem": onuGemData})
1997 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
1998 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001999 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002000 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002001 }
2002 }
2003 dh.onus.Delete(onuKey)
2004 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2005 return nil
2006}
Girish Gowdracefae192020-03-19 18:14:10 -07002007
2008func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2009 for _, field := range flows.GetOfbFields(flow) {
2010 if field.Type == flows.IN_PORT {
2011 return field.GetPort()
2012 }
2013 }
2014 return InvalidPort
2015}
2016
2017func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2018 for _, action := range flows.GetActions(flow) {
2019 if action.Type == flows.OUTPUT {
2020 if out := action.GetOutput(); out != nil {
2021 return out.GetPort()
2022 }
2023 }
2024 }
2025 return InvalidPort
2026}
2027
2028func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2029 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002030 logger.Debugw("increment flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002031 if inPort != InvalidPort && outPort != InvalidPort {
2032 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2033 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002034 logger.Debugw("increment flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002035
2036 dh.lockDevice.Lock()
2037 defer dh.lockDevice.Unlock()
2038 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2039 if !ok {
2040 flowRemoveData = pendingFlowRemoveData{
2041 pendingFlowRemoveCount: 0,
2042 allFlowsRemoved: make(chan struct{}),
2043 }
2044 }
2045 flowRemoveData.pendingFlowRemoveCount++
2046 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2047
Girish Kumar2ad402b2020-03-20 19:45:12 +00002048 logger.Debugw("current flow remove count after increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002049 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2050 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2051 }
2052}
2053
2054func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2055 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002056 logger.Debugw("decrement flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002057 if inPort != InvalidPort && outPort != InvalidPort {
2058 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2059 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002060 logger.Debugw("decrement flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002061
2062 dh.lockDevice.Lock()
2063 defer dh.lockDevice.Unlock()
2064 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002065 logger.Fatalf("flow remove key not found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002066 } else {
2067 if val.pendingFlowRemoveCount > 0 {
2068 val.pendingFlowRemoveCount--
2069 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002070 logger.Debugw("current flow remove count after decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002071 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2072 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2073 // If all flow removes have finished, then close the channel to signal the receiver
2074 // to go ahead with flow adds.
2075 if val.pendingFlowRemoveCount == 0 {
2076 close(val.allFlowsRemoved)
2077 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2078 return
2079 }
2080 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2081 }
2082 }
2083}
2084
2085func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2086 var flowRemoveData pendingFlowRemoveData
2087 var ok bool
2088 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002089 logger.Debugw("wait for flow remove to finish for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002090 if inPort != InvalidPort && outPort != InvalidPort {
2091 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2092 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002093 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 -07002094
2095 dh.lockDevice.RLock()
2096 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002097 logger.Debugw("no pending flow to remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002098 dh.lockDevice.RUnlock()
2099 return
2100 }
2101 dh.lockDevice.RUnlock()
2102
2103 // Wait for all flow removes to finish first
2104 <-flowRemoveData.allFlowsRemoved
2105
Girish Kumar2ad402b2020-03-20 19:45:12 +00002106 logger.Debugw("all flows cleared, handling flow add now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002107 }
2108}
2109
2110func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2111 inPort := getInPortFromFlow(flow)
2112 outPort := getOutPortFromFlow(flow)
2113
2114 if inPort == InvalidPort || outPort == InvalidPort {
2115 return inPort, outPort
2116 }
2117
2118 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2119 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2120 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2121 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2122 return uniPort, outPort
2123 }
2124 }
2125 } else {
2126 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2127 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2128 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2129 return inPort, uniPort
2130 }
2131 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2132 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2133 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2134 return uniPort, outPort
2135 }
2136 }
2137 }
2138
2139 return InvalidPort, InvalidPort
2140}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002141
2142func extractOmciTransactionID(omciPkt []byte) uint16 {
2143 if len(omciPkt) > 3 {
2144 d := omciPkt[0:2]
2145 transid := binary.BigEndian.Uint16(d)
2146 return transid
2147 }
2148 return 0
2149}