blob: 6b7ca7e3f0927dc29b68109a09c433759ec9ba95 [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 {
Thomas Lee S85f37312020-04-03 17:06:12 +0530535 //starting the stat collector
536 go startCollector(dh)
537
Girish Gowdru0c588b22019-04-23 23:24:56 -0400538 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530539 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400540 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000541 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400542 }
543 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530544}
545
546// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530547func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700548 dh.lockDevice.Lock()
549 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000550 logger.Debug("do-state-down-start")
Girish Gowdrud4245152019-05-10 00:47:31 -0400551
npujarec5762e2020-01-01 14:08:48 +0530552 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400553 if err != nil || device == nil {
554 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000555 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400556 }
557
558 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400559
560 //Update the device oper state and connection status
561 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400562 dh.device = cloned
563
David K. Bainbridge794735f2020-02-11 21:01:37 -0800564 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000565 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400566 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400567
568 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530569 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400570 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000571 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400572 }
573 for _, onuDevice := range onuDevices.Items {
574
575 // Update onu state as down in onu adapter
576 onuInd := oop.OnuIndication{}
577 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800578 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700579 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800580 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530581 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800582 "source": "openolt",
583 "onu-indicator": onuInd,
584 "device-type": onuDevice.Type,
585 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700586 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700587 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400588 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700589 /* Discovered ONUs entries need to be cleared , since after OLT
590 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530591 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000592 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700593 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530594}
595
596// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530597func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400598 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800599 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530600 return olterrors.NewErrCommunication("dial-failure", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800601 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000602 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400603 }
604 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530605}
606
607// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530608func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400609 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530610 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400611 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530612}
613
614// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530615func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000616 logger.Debug("OLT device has been connected")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400617
618 // Case where OLT is disabled and then rebooted.
619 if dh.adminState == "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000620 logger.Debugln("do-state-connected--device-admin-state-down")
npujarec5762e2020-01-01 14:08:48 +0530621 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400622 if err != nil || device == nil {
623 /*TODO: needs to handle error scenarios */
Thomas Lee S94109f12020-03-03 16:39:29 +0530624 olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400625 }
626
627 cloned := proto.Clone(device).(*voltha.Device)
628 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
629 cloned.OperStatus = voltha.OperStatus_UNKNOWN
630 dh.device = cloned
npujarec5762e2020-01-01 14:08:48 +0530631 if er := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); er != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530632 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400633 }
634
Chaitrashree G S44124192019-08-07 20:21:36 -0400635 // Since the device was disabled before the OLT was rebooted, enforce the OLT to be Disabled after re-connection.
npujarec5762e2020-01-01 14:08:48 +0530636 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400637 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530638 olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400639 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400640 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
641 // all the modules initialized and ready to handle incoming ONUs.
642
643 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
644 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
645 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400646
647 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800648 go func() {
649 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530650 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800651 }
652 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400653 return nil
654 }
655
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700656 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400657 if err != nil || device == nil {
658 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000659 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400660 }
kesavand39e0aa32020-01-28 20:58:50 -0500661 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500662 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000663 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400664 }
665
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400666 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
667 olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400668 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530669
cuilin20187b2a8c32019-03-26 19:52:28 -0700670 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800671 go func() {
672 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530673 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800674 }
675 }()
cuilin20187b2a8c32019-03-26 19:52:28 -0700676 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530677}
678
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400679func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
680 deviceInfo, err := dh.populateDeviceInfo()
681
682 if err != nil {
683 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
684 }
685 KVStoreHostPort := fmt.Sprintf("%s:%d", dh.openOLT.KVStoreHost, dh.openOLT.KVStorePort)
686 // Instantiate resource manager
687 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.deviceID, KVStoreHostPort, dh.openOLT.KVStoreType, dh.deviceType, deviceInfo); dh.resourceMgr == nil {
688 return olterrors.ErrResourceManagerInstantiating
689 }
690
691 // Instantiate flow manager
692 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
693 return olterrors.ErrResourceManagerInstantiating
694
695 }
696 /* TODO: Instantiate Alarm , stats , BW managers */
697 /* Instantiating Event Manager to handle Alarms and KPIs */
698 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
699
700 // Stats config for new device
701 dh.portStats = NewOpenOltStatsMgr(dh)
702
703 return nil
704
705}
706
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400707func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
708 var err error
709 var deviceInfo *oop.DeviceInfo
710
711 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
712
713 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000714 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400715 }
716 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000717 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400718 }
719
Girish Kumar2ad402b2020-03-20 19:45:12 +0000720 logger.Debugw("Fetched device info", log.Fields{"deviceInfo": deviceInfo})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400721 dh.device.Root = true
722 dh.device.Vendor = deviceInfo.Vendor
723 dh.device.Model = deviceInfo.Model
724 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
725 dh.device.HardwareVersion = deviceInfo.HardwareVersion
726 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
727
728 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000729 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400730 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
731 genmac, err := generateMacFromHost(host)
732 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000733 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400734 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000735 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400736 dh.device.MacAddress = genmac
737 } else {
738 dh.device.MacAddress = deviceInfo.DeviceId
739 }
740
741 // Synchronous call to update device - this method is run in its own go routine
742 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000743 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400744 }
745
746 return deviceInfo, nil
747}
748
Naga Manjunath7615e552019-10-11 22:35:47 +0530749func startCollector(dh *DeviceHandler) {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000750 logger.Debugf("Starting-Collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530751 context := make(map[string]string)
752 for {
753 select {
754 case <-dh.stopCollector:
Girish Kumar2ad402b2020-03-20 19:45:12 +0000755 logger.Debugw("Stopping-Collector-for-OLT", log.Fields{"deviceID:": dh.deviceID})
Naga Manjunath7615e552019-10-11 22:35:47 +0530756 return
757 default:
758 freq := dh.metrics.ToPmConfigs().DefaultFreq
759 time.Sleep(time.Duration(freq) * time.Second)
760 context["oltid"] = dh.deviceID
761 context["devicetype"] = dh.deviceType
762 // NNI Stats
763 cmnni := dh.portStats.collectNNIMetrics(uint32(0))
Girish Kumar2ad402b2020-03-20 19:45:12 +0000764 logger.Debugf("Collect-NNI-Metrics %v", cmnni)
Naga Manjunath7615e552019-10-11 22:35:47 +0530765 go dh.portStats.publishMetrics("NNIStats", cmnni, uint32(0), context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000766 logger.Debugf("Publish-NNI-Metrics")
Naga Manjunath7615e552019-10-11 22:35:47 +0530767 // PON Stats
768 NumPonPORTS := dh.resourceMgr.DevInfo.GetPonPorts()
Chaitrashree G Sef088112020-02-03 21:39:27 -0500769 for i := uint32(0); i < NumPonPORTS; i++ {
770 if val, ok := dh.activePorts.Load(i); ok && val == true {
771 cmpon := dh.portStats.collectPONMetrics(i)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000772 logger.Debugf("Collect-PON-Metrics %v", cmpon)
Chaitrashree G Sef088112020-02-03 21:39:27 -0500773 go dh.portStats.publishMetrics("PONStats", cmpon, i, context, dh.deviceID)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000774 logger.Debugf("Publish-PON-Metrics")
Chaitrashree G Sef088112020-02-03 21:39:27 -0500775 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530776 }
777 }
778 }
779}
780
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700781//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530782func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400783 dh.transitionMap = NewTransitionMap(dh)
Girish Kumar2ad402b2020-03-20 19:45:12 +0000784 logger.Infow("Adopt_device", log.Fields{"deviceID": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530785 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530786
787 // Now, set the initial PM configuration for that device
788 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530789 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530790 }
791
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400792 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530793}
794
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700795//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530796func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700797 return &ic.SwitchCapability{
798 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530799 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700800 HwDesc: "open_pon",
801 SwDesc: "open_pon",
802 SerialNum: dh.device.SerialNumber,
803 },
804 SwitchFeatures: &of.OfpSwitchFeatures{
805 NBuffers: 256,
806 NTables: 2,
807 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
808 of.OfpCapabilities_OFPC_TABLE_STATS |
809 of.OfpCapabilities_OFPC_PORT_STATS |
810 of.OfpCapabilities_OFPC_GROUP_STATS),
811 },
812 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530813}
814
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700815//GetOfpPortInfo Get Ofp port information
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530816func (dh *DeviceHandler) GetOfpPortInfo(device *voltha.Device, portNo int64) (*ic.PortCapability, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700817 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
cuilin20187b2a8c32019-03-26 19:52:28 -0700818 return &ic.PortCapability{
819 Port: &voltha.LogicalPort{
820 OfpPort: &of.OfpPort{
821 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
822 Config: 0,
823 State: uint32(of.OfpPortState_OFPPS_LIVE),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700824 Curr: capacity,
825 Advertised: capacity,
826 Peer: capacity,
cuilin20187b2a8c32019-03-26 19:52:28 -0700827 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
828 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
829 },
830 DeviceId: dh.device.Id,
831 DevicePortNo: uint32(portNo),
832 },
833 }, nil
834}
835
David K. Bainbridge794735f2020-02-11 21:01:37 -0800836func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000837 logger.Debugw("omci indication", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700838 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700839 var deviceID string
840 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700841
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400842 transid := extractOmciTransactionID(omciInd.Pkt)
843 logger.Debugw("recv-omci-msg", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId,
844 "omciTransactionID": transid, "omciMsg": hex.EncodeToString(omciInd.Pkt)})
845
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700846 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530847
848 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
849
Girish Kumar2ad402b2020-03-20 19:45:12 +0000850 logger.Debugw("omci indication for a device not in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700851 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700852 kwargs := make(map[string]interface{})
853 kwargs["onu_id"] = omciInd.OnuId
854 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700855
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700856 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
857 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530858 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800859 "interface-id": omciInd.IntfId,
Girish Kumarf26e4882020-03-05 06:49:10 +0000860 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700861 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700862 deviceType = onuDevice.Type
863 deviceID = onuDevice.Id
864 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
865 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530866 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700867 } else {
868 //found in cache
Girish Kumar2ad402b2020-03-20 19:45:12 +0000869 logger.Debugw("omci indication for a device in cache.", log.Fields{"intfID": omciInd.IntfId, "onuID": omciInd.OnuId})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530870 deviceType = onuInCache.(*OnuDevice).deviceType
871 deviceID = onuInCache.(*OnuDevice).deviceID
872 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700873 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700874
875 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800876 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700877 ic.InterAdapterMessageType_OMCI_REQUEST, dh.deviceType, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800878 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530879 return olterrors.NewErrCommunication("omci-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800880 "source": dh.deviceType,
881 "destination": deviceType,
882 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000883 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700884 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800885 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530886}
887
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700888//ProcessInterAdapterMessage sends the proxied messages to the target device
889// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
890// is meant, and then send the unmarshalled omci message to this onu
891func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000892 logger.Debugw("Process_inter_adapter_message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700893 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700894 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700895 fromTopic := msg.Header.FromTopic
896 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700897 toDeviceID := msg.Header.ToDeviceId
898 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700899
Girish Kumar2ad402b2020-03-20 19:45:12 +0000900 logger.Debugw("omci request message header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700901
902 msgBody := msg.GetBody()
903
904 omciMsg := &ic.InterAdapterOmciMessage{}
905 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000906 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700907 }
908
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700909 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700910 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
911 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530912 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800913 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000914 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700915 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000916 logger.Debugw("device retrieved from core", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800917 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530918 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800919 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000920 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800921 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700922 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000923 logger.Debugw("Proxy Address found in omci message", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800924 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530925 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800926 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000927 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800928 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700929 }
930
931 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000932 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700933 }
934 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530935}
936
David K. Bainbridge794735f2020-02-11 21:01:37 -0800937func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938 var intfID uint32
939 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000940 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700941 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 intfID = onuDevice.ProxyAddress.GetChannelId()
943 onuID = onuDevice.ProxyAddress.GetOnuId()
944 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700945 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700946 intfID = omciMsg.GetProxyAddress().GetChannelId()
947 onuID = omciMsg.GetProxyAddress().GetOnuId()
948 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700949 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700950 if connectStatus != voltha.ConnectStatus_REACHABLE {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000951 logger.Debugw("ONU is not reachable, cannot send OMCI", log.Fields{"intfID": intfID, "onuID": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800952
Thomas Lee S94109f12020-03-03 16:39:29 +0530953 return olterrors.NewErrCommunication("unreachable", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800954 "interface-id": intfID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000955 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700956 }
957
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400958 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
959 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -0700960 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400961 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
962 hex.Encode(hexPkt, omciMsg.Message)
963 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
964
965 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
966 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
967 transid := extractOmciTransactionID(omciMsg.Message)
968 logger.Debugw("sent-omci-msg", log.Fields{"intfID": intfID, "onuID": onuID,
969 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -0700970
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700971 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
972 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530973 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800974 "interface-id": intfID,
975 "onu-id": onuID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000976 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700977 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800978 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700979}
980
David K. Bainbridge794735f2020-02-11 21:01:37 -0800981func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000982 logger.Debugw("activate-onu", log.Fields{"intfID": intfID, "onuID": onuID, "serialNum": serialNum, "serialNumber": serialNumber})
Andrea Campanellab83b39d2020-03-30 11:41:16 +0200983 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
984 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intfID": intfID}, err)
985 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700986 // TODO: need resource manager
987 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +0530989 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400990 st, _ := status.FromError(err)
991 if st.Code() == codes.AlreadyExists {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000992 logger.Debug("ONU activation is in progress", log.Fields{"SerialNumber": serialNumber})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400993 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000994 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400995 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700996 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000997 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber})
cuilin20187b2a8c32019-03-26 19:52:28 -0700998 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800999 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001000}
1001
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001003
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001004 channelID := onuDiscInd.GetIntfId()
1005 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001006
Girish Kumar2ad402b2020-03-20 19:45:12 +00001007 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301008
cuilin20187b2a8c32019-03-26 19:52:28 -07001009 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001010 if sn != "" {
1011 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001012 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001013 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001014 }
1015
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301016 var alarmInd oop.OnuAlarmIndication
1017 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001018 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301019
1020 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1021 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1022 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1023 OnuLosRaise event sent for it */
1024 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1025 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1026 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001027 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301028 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1029 "currentIntfId": onuDiscInd.GetIntfId()})
1030 // TODO:: Should we need to ignore raising OnuLosClear event
1031 // when onu connected to different PON?
1032 }
1033 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1034 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1035 alarmInd.LosStatus = statusCheckOff
1036 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1037 }
1038 return true
1039 })
1040
Girish Kumar2ad402b2020-03-20 19:45:12 +00001041 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001043 }
1044
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001045 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001046
1047 // check the ONU is already know to the OLT
1048 // NOTE the second time the ONU is discovered this should return a device
1049 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1050
1051 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001052 logger.Warnw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001053 if e, ok := status.FromError(err); ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001054 logger.Warnw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001055 switch e.Code() {
1056 case codes.Internal:
1057 // this probably means NOT FOUND, so just create a new device
1058 onuDevice = nil
1059 case codes.DeadlineExceeded:
1060 // if the call times out, cleanup and exit
1061 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001062 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001063 }
1064 }
1065 }
1066
1067 if onuDevice == nil {
1068 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Girish Kumar2ad402b2020-03-20 19:45:12 +00001069 logger.Infow("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001070 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001071 ponintfid := onuDiscInd.GetIntfId()
1072 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301073 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001074 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001075
Girish Kumar2ad402b2020-03-20 19:45:12 +00001076 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001077
1078 if err != nil {
1079 // if we can't create an ID in resource manager,
1080 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001081 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001082 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001083 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001084 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001085 }
1086
1087 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1088 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001089 dh.discOnus.Delete(sn)
1090 dh.resourceMgr.FreeonuID(ctx, ponintfid, []uint32{onuID}) // NOTE I'm not sure this method is actually cleaning up the right thing
Thomas Lee S94109f12020-03-03 16:39:29 +05301091 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001092 "pon-interface-id": ponintfid,
Girish Kumarf26e4882020-03-05 06:49:10 +00001093 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001094 }
Devmalya Paulbcdb1442020-03-03 17:28:08 -05001095 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Girish Kumar2ad402b2020-03-20 19:45:12 +00001096 logger.Infow("onu-child-device-added", log.Fields{"onuDevice": onuDevice, "sn": sn})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001097 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001098
1099 // we can now use the existing ONU Id
1100 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001101 //Insert the ONU into cache to use in OnuIndication.
1102 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001103 logger.Debugw("onu-discovery-indication-key-create", log.Fields{"onuID": onuID,
Matteo Scandolo945e4012019-12-12 14:16:11 -08001104 "intfId": onuDiscInd.GetIntfId(), "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001105 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001106
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301107 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301108 dh.onus.Store(onuKey, onuDev)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001109 logger.Debugw("new-onu-device-discovered", log.Fields{"onu": onuDev, "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001110
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301112 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001114 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001115 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001116 logger.Infow("onu-discovered-reachable", log.Fields{"deviceId": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001117 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301118 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001119 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001120 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001121 }
1122 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001123}
1124
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001126 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1127
1128 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001129 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001130 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001131 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001132 foundInCache := false
Girish Kumar2ad402b2020-03-20 19:45:12 +00001133 logger.Debugw("ONU indication key create", log.Fields{"onuId": onuInd.OnuId,
Scott Baker7eb0a932019-07-26 10:33:22 -07001134 "intfId": onuInd.GetIntfId()})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001135 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301136
David K. Bainbridge794735f2020-02-11 21:01:37 -08001137 errFields := log.Fields{"device-id": dh.device.Id}
1138
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301139 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1140
Mahir Gunyele77977b2019-06-27 05:36:22 -07001141 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1142 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001143 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1144 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001145 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001146 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1147 if serialNumber != "" {
1148 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001150 } else {
1151 kwargs["onu_id"] = onuInd.OnuId
1152 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 errFields["onu-id"] = onuInd.OnuId
1154 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001155 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001157 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001158
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001160 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001161 }
1162
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 if onuDevice.ParentPortNo != ponPort {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001164 logger.Warnw("ONU-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 "previousIntfId": onuDevice.ParentPortNo,
1166 "currentIntfId": ponPort})
1167 }
1168
1169 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001170 logger.Warnw("ONU-id-mismatch, can happen if both voltha and the olt rebooted", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 "expected_onu_id": onuDevice.ProxyAddress.OnuId,
1172 "received_onu_id": onuInd.OnuId})
1173 }
1174 if !foundInCache {
1175 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1176
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301177 dh.onus.Store(onuKey, NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuInd.GetOnuId(), onuInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false))
David K. Bainbridge794735f2020-02-11 21:01:37 -08001178
1179 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001180 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001181 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001182 }
1183 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001184}
1185
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001186func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301187 ctx := context.TODO()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001188 logger.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001189 if onuInd.AdminState == "down" {
1190 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1191 if onuInd.OperState != "down" {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001192 logger.Warnw("ONU-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001193 onuInd.OperState = "down"
1194 }
1195 }
1196
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 switch onuInd.OperState {
1198 case "down":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001199 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001200 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301201 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001202 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1203 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301204 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001205 "onu-indicator": onuInd,
1206 "source": "openolt",
1207 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001208 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001209 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 case "up":
Girish Kumar2ad402b2020-03-20 19:45:12 +00001211 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "DeviceId": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Matt Jeanneret53539512019-07-20 14:47:02 -04001212 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301213 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001214 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1215 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301216 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001217 "onu-indicator": onuInd,
1218 "source": "openolt",
1219 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001220 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001221 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001223 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001224 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001225 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001226}
1227
cuilin20187b2a8c32019-03-26 19:52:28 -07001228func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1229 if serialNum != nil {
1230 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001231 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001232 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001233}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001234func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1235 decodedStr, err := hex.DecodeString(serialNum[4:])
1236 if err != nil {
1237 return nil, err
1238 }
1239 return &oop.SerialNumber{
1240 VendorId: []byte(serialNum[:4]),
1241 VendorSpecific: []byte(decodedStr),
1242 }, nil
1243}
cuilin20187b2a8c32019-03-26 19:52:28 -07001244
1245func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1246 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001247 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001248 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1249 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1250 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1251 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1252 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1253 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1254 return tmp
1255}
1256
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001257//UpdateFlowsBulk upates the bulk flow
1258func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301259 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001260}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001261
1262//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001264 logger.Debugw("GetChildDevice", log.Fields{"pon port": parentPort, "onuID": onuID})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001265 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001266 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001267 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001268 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001269 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001270 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001271 "interface-id": parentPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001272 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001273 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001274 logger.Debugw("Successfully received child device from core", log.Fields{"child_device": *onuDevice})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301276}
1277
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001278// SendPacketInToCore sends packet-in to core
1279// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1280// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001282 logger.Debugw("send-packet-in-to-core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001283 "port": logicalPort,
1284 "packet": hex.EncodeToString(packetPayload),
1285 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001286 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301287 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001288 "source": "adapter",
1289 "destination": "core",
1290 "device-id": dh.device.Id,
1291 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001292 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001293 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001294 logger.Debugw("Sent packet-in to core successfully", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001295 "packet": hex.EncodeToString(packetPayload),
1296 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001297 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001298}
1299
A R Karthick1f85b802019-10-11 05:06:05 +00001300// AddUniPortToOnu adds the uni port to the onu device
1301func (dh *DeviceHandler) AddUniPortToOnu(intfID, onuID, uniPort uint32) {
1302 onuKey := dh.formOnuKey(intfID, onuID)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301303
1304 if onuDevice, ok := dh.onus.Load(onuKey); ok {
A R Karthick1f85b802019-10-11 05:06:05 +00001305 // add it to the uniPort map for the onu device
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301306 if _, ok = onuDevice.(*OnuDevice).uniPorts[uniPort]; !ok {
1307 onuDevice.(*OnuDevice).uniPorts[uniPort] = struct{}{}
Girish Kumar2ad402b2020-03-20 19:45:12 +00001308 logger.Debugw("adding-uni-port", log.Fields{"port": uniPort, "intfID": intfID, "onuId": onuID})
A R Karthick1f85b802019-10-11 05:06:05 +00001309 }
1310 }
1311}
1312
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001313//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301314func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001315 logger.Debugw("Received-incremental-flowupdate-in-device-handler", log.Fields{"deviceID": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001316
1317 var errorsList []error
1318
Girish Gowdru0c588b22019-04-23 23:24:56 -04001319 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001320 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001321 dh.incrementActiveFlowRemoveCount(flow)
1322
Girish Kumar2ad402b2020-03-20 19:45:12 +00001323 logger.Debug("Removing flow", log.Fields{"deviceId": device.Id, "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001324 err := dh.flowMgr.RemoveFlow(ctx, flow)
1325 if err != nil {
1326 errorsList = append(errorsList, err)
1327 }
1328
1329 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001330 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301331
1332 for _, flow := range flows.ToAdd.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001333 logger.Debug("Adding flow", log.Fields{"deviceId": device.Id, "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001334 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1335 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001336 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1337 if err != nil {
1338 errorsList = append(errorsList, err)
1339 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301340 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001341 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001342 if groups != nil && flows != nil {
Girish Gowdru0c588b22019-04-23 23:24:56 -04001343 for _, flow := range flows.ToRemove.Items {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001344 logger.Debug("Removing flow", log.Fields{"deviceID": device.Id, "flowToRemove": flow})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001345 // dh.flowMgr.RemoveFlow(flow)
1346 }
1347 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001348
Girish Gowdracefae192020-03-19 18:14:10 -07001349 // Whether we need to synchronize multicast group adds and modifies like flow add and delete needs to be investigated
Esin Karamanccb714b2019-11-29 15:02:06 +00001350 if groups != nil {
1351 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001352 err := dh.flowMgr.AddGroup(ctx, group)
1353 if err != nil {
1354 errorsList = append(errorsList, err)
1355 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001356 }
1357 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001358 err := dh.flowMgr.ModifyGroup(ctx, group)
1359 if err != nil {
1360 errorsList = append(errorsList, err)
1361 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001362 }
1363 if len(groups.ToRemove.Items) != 0 {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001364 logger.Debug("Group delete operation is not supported for now")
Esin Karamanccb714b2019-11-29 15:02:06 +00001365 }
1366 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001367 if len(errorsList) > 0 {
1368 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1369 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001370 logger.Debug("UpdateFlowsIncrementally done successfully")
Girish Gowdru0c588b22019-04-23 23:24:56 -04001371 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301372}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001373
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001374//DisableDevice disables the given device
1375//It marks the following for the given device:
1376//Device-Handler Admin-State : down
1377//Device Port-State: UNKNOWN
1378//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001379func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001380 /* On device disable ,admin state update has to be done prior sending request to agent since
1381 the indication thread may processes invalid indications of ONU and OLT*/
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001382 dh.lockDevice.Lock()
1383 dh.adminState = "down"
1384 dh.lockDevice.Unlock()
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001385 if dh.Client != nil {
1386 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1387 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001388 dh.lockDevice.Lock()
1389 dh.adminState = "up"
1390 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001391 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001392 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001393 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001394 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001395 logger.Debugw("olt-disabled", log.Fields{"deviceID": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001396 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001397 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301398
1399 dh.discOnus = sync.Map{}
1400 dh.onus = sync.Map{}
1401
Thomas Lee S85f37312020-04-03 17:06:12 +05301402 //stopping the stats collector
1403 dh.stopCollector <- true
1404
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301405 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001406 cloned := proto.Clone(device).(*voltha.Device)
kdarapu1afeceb2020-02-12 01:38:09 -05001407 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1408 for _, port := range cloned.Ports {
1409 if port.GetType() == voltha.Port_PON_OLT {
1410 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1411 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001412 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001413 }
1414 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001415 }
1416
Girish Kumar2ad402b2020-03-20 19:45:12 +00001417 logger.Debugw("disable-device-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001418 return nil
1419}
1420
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301421func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001422
1423 // Update onu state as unreachable in onu adapter
1424 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301425 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001426 //get the child device for the parent device
1427 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1428 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001429 logger.Errorw("failed-to-get-child-devices-information", log.Fields{"deviceID": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001430 }
1431 if onuDevices != nil {
1432 for _, onuDevice := range onuDevices.Items {
1433 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1434 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1435 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001436 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001437 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "DeviceID": onuDevice.Id})
1438 }
1439
1440 }
1441 }
1442
1443}
1444
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445//ReenableDevice re-enables the olt device after disable
1446//It marks the following for the given device:
1447//Device-Handler Admin-State : up
1448//Device Port-State: ACTIVE
1449//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001450func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001451 dh.lockDevice.Lock()
1452 dh.adminState = "up"
1453 dh.lockDevice.Unlock()
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301454
1455 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1456 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301457 dh.lockDevice.Lock()
1458 dh.adminState = "down"
1459 dh.lockDevice.Unlock()
Girish Kumarf26e4882020-03-05 06:49:10 +00001460 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301461 }
1462 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001463 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001464
1465 cloned := proto.Clone(device).(*voltha.Device)
1466 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001467
kdarapu1afeceb2020-02-12 01:38:09 -05001468 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001469 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001470 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001471 //Update the device oper status as ACTIVE
1472 cloned.OperStatus = voltha.OperStatus_ACTIVE
1473 dh.device = cloned
1474
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001475 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301476 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001477 "device-id": device.Id,
1478 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001479 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001480 }
kesavand39e0aa32020-01-28 20:58:50 -05001481
Girish Kumar2ad402b2020-03-20 19:45:12 +00001482 logger.Debugw("ReEnableDevice-end", log.Fields{"deviceID": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001483
1484 return nil
1485}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001486
npujarec5762e2020-01-01 14:08:48 +05301487func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001488 var uniID uint32
1489 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301490 for _, port := range onu.UniPorts {
1491 uniID = UniIDFromPortNum(uint32(port))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001492 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uniID": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001493 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301494 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001495 logger.Debugw("Failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001496 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001497 logger.Debugw("Deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301498 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001499 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301500 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001501 }
npujarec5762e2020-01-01 14:08:48 +05301502 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001503 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301504 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001505 logger.Debugw("Failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001506 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001507 logger.Debugw("Removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301508 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001509 logger.Debugw("Failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001510 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001511 logger.Debugw("Removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301512 }
npujarec5762e2020-01-01 14:08:48 +05301513 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1514 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001515 logger.Debugw("Failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301516 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001517 logger.Debugw("Removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301518 if err = dh.resourceMgr.DelGemPortPktIn(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001519 logger.Debugw("Failed-to-remove-gemport-pkt-in", log.Fields{"intfid": onu.IntfID, "onuid": onu.OnuID, "uniId": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001520 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001521 }
1522 return nil
1523}
1524
npujarec5762e2020-01-01 14:08:48 +05301525func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001526 nniUniID := -1
1527 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301528
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001529 if dh.resourceMgr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001530 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.deviceID}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001531 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001532 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301533 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301534 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001535 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001536 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001537 logger.Debugw("NNI are ", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301538 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301539 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Girish Kumar2ad402b2020-03-20 19:45:12 +00001540 logger.Debugw("Current flow ids for nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301541 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301542 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301543 }
npujarec5762e2020-01-01 14:08:48 +05301544 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001545 }
npujarec5762e2020-01-01 14:08:48 +05301546 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001547 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301548 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001549 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001550}
1551
1552// DeleteDevice deletes the device instance from openolt handler array. Also clears allocated resource manager resources. Also reboots the OLT hardware!
npujarec5762e2020-01-01 14:08:48 +05301553func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001554 logger.Debug("Function entry delete device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001555 dh.lockDevice.Lock()
A R Karthick1f85b802019-10-11 05:06:05 +00001556 if dh.adminState == "deleted" {
1557 dh.lockDevice.Unlock()
1558 return nil
1559 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001560 dh.adminState = "deleted"
1561 dh.lockDevice.Unlock()
1562 /* Clear the KV store data associated with the all the UNI ports
1563 This clears up flow data and also resource map data for various
1564 other pon resources like alloc_id and gemport_id
1565 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001566 go dh.cleanupDeviceResources(ctx)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001567 logger.Debug("Removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001568 // Stop the Stats collector
1569 dh.stopCollector <- true
1570 // stop the heartbeat check routine
1571 dh.stopHeartbeatCheck <- true
1572 //Reset the state
1573 if dh.Client != nil {
1574 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
1575 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err).Log()
1576 }
1577 }
1578 cloned := proto.Clone(device).(*voltha.Device)
1579 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1580 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1581 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1582 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1583 "device-id": device.Id,
1584 "connect-status": cloned.ConnectStatus,
1585 "oper-status": cloned.OperStatus}, err).Log()
1586 }
1587 return nil
1588}
1589func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001590 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301591 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1592 var ponPort uint32
1593 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1594 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301595 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301596 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301597 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001598 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001599 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301600 }
1601 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301602 onuID := make([]uint32, 1)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001603 logger.Debugw("onu data ", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301604 if err = dh.clearUNIData(ctx, &onu); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001605 logger.Errorw("Failed to clear data for onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301606 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301607 // Clear flowids for gem cache.
1608 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301609 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301610 }
1611 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301612 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301613 }
npujarec5762e2020-01-01 14:08:48 +05301614 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301615 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301616 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301617 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001618 logger.Errorw("Failed to update onugem info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001619 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001620 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001621 /* Clear the flows from KV store associated with NNI port.
1622 There are mostly trap rules from NNI port (like LLDP)
1623 */
npujarec5762e2020-01-01 14:08:48 +05301624 if err := dh.clearNNIData(ctx); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001625 logger.Errorw("Failed to clear data for NNI port", log.Fields{"device-id": dh.deviceID})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001626 }
A R Karthick1f85b802019-10-11 05:06:05 +00001627
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001628 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301629 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001630 }
A R Karthick1f85b802019-10-11 05:06:05 +00001631
Devmalya Paul495b94a2019-08-27 19:42:00 -04001632 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301633 dh.onus.Range(func(key interface{}, value interface{}) bool {
1634 dh.onus.Delete(key)
1635 return true
1636 })
1637
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001638 /*Delete discovered ONU map for the device*/
1639 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1640 dh.discOnus.Delete(key)
1641 return true
1642 })
1643
Devmalya Paul495b94a2019-08-27 19:42:00 -04001644 return nil
1645}
1646
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001647//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001648func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1649 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001650 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.deviceID}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001651 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001652 logger.Debugw("rebooted-device-successfully", log.Fields{"deviceID": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001653 return nil
1654}
1655
David K. Bainbridge794735f2020-02-11 21:01:37 -08001656func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001657 logger.Debugw("Received packet-in", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001658 "packet-indication": *packetIn,
1659 "packet": hex.EncodeToString(packetIn.Pkt),
1660 })
npujarec5762e2020-01-01 14:08:48 +05301661 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001662 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001663 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001664 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001665 logger.Debugw("sending packet-in to core", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001666 "logicalPortNum": logicalPortNum,
1667 "packet": hex.EncodeToString(packetIn.Pkt),
1668 })
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001669 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301670 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001671 "destination": "core",
1672 "source": dh.deviceType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001673 "packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001674 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001675 logger.Debugw("Success sending packet-in to core!", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001676 "packet": hex.EncodeToString(packetIn.Pkt),
1677 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001679}
1680
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001681// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301682func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001683 logger.Debugw("incoming-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001684 "deviceID": dh.deviceID,
1685 "egress_port_no": egressPortNo,
1686 "pkt-length": len(packet.Data),
1687 "packet": hex.EncodeToString(packet.Data),
1688 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001689
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001690 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001691 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001692 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1693 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301694 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1695 // Do not packet-out lldp packets on uni port.
1696 // ONOS has no clue about uni/nni ports, it just packets out on all
1697 // available ports on the Logical Switch. It should not be interested
1698 // in the UNI links.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001699 logger.Debug("dropping-lldp-packet-out-on-uni")
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301700 return nil
1701 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001702 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1703 if innerEthType == 0x8100 {
1704 // q-in-q 802.1ad or 802.1q double tagged packet.
1705 // slice out the outer tag.
1706 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001707 logger.Debugw("packet-now-single-tagged", log.Fields{"packetData": hex.EncodeToString(packet.Data)})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001708 }
1709 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001710 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1711 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001712 uniID := UniIDFromPortNum(uint32(egressPortNo))
1713
npujarec5762e2020-01-01 14:08:48 +05301714 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001715 if err != nil {
1716 // In this case the openolt agent will receive the gemPortID as 0.
1717 // The agent tries to retrieve the gemPortID in this case.
1718 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001719 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001720 "packet": hex.EncodeToString(packet.Data),
1721 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001722 }
1723
1724 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001725
Girish Kumar2ad402b2020-03-20 19:45:12 +00001726 logger.Debugw("sending-packet-to-onu", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001727 "egress_port_no": egressPortNo,
1728 "IntfId": intfID,
1729 "onuID": onuID,
1730 "uniID": uniID,
1731 "gemPortID": gemPortID,
1732 "packet": hex.EncodeToString(packet.Data),
1733 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001734
npujarec5762e2020-01-01 14:08:48 +05301735 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301736 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001737 "source": "adapter",
1738 "destination": "onu",
1739 "egress-port-number": egressPortNo,
1740 "interface-id": intfID,
1741 "oni-id": onuID,
1742 "uni-id": uniID,
1743 "gem-port-id": gemPortID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001744 "packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001745 }
1746 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001747 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1748 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001749 return olterrors.NewErrInvalidValue(log.Fields{"egress-nni-port": egressPortNo}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001750 }
1751 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001752
Girish Kumar2ad402b2020-03-20 19:45:12 +00001753 logger.Debugw("sending-packet-to-nni", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001754 "uplink_pkt": uplinkPkt,
1755 "packet": hex.EncodeToString(packet.Data),
1756 })
Matt Jeanneret1359c732019-08-01 21:40:02 -04001757
npujarec5762e2020-01-01 14:08:48 +05301758 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001759 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{"packet": hex.EncodeToString(packet.Data)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001760 }
1761 } else {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001762 logger.Warnw("Packet-out-to-this-interface-type-not-implemented", log.Fields{
Matteo Scandolo6056e822019-11-13 14:05:29 -08001763 "egress_port_no": egressPortNo,
1764 "egressPortType": egressPortType,
1765 "packet": hex.EncodeToString(packet.Data),
1766 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001767 }
1768 return nil
1769}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001770
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001771func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1772 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001773}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301774
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001775func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301776 // start the heartbeat check towards the OLT.
1777 var timerCheck *time.Timer
1778
1779 for {
1780 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1781 select {
1782 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001783 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1784 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001785 logger.Error("Hearbeat failed")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301786 if timerCheck == nil {
1787 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001788 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301789 }
1790 } else {
1791 if timerCheck != nil {
1792 if timerCheck.Stop() {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001793 logger.Debug("We got hearbeat within the timeout")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301794 }
1795 timerCheck = nil
1796 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001797 logger.Debugw("Hearbeat", log.Fields{"signature": heartBeat})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301798 }
1799 cancel()
1800 case <-dh.stopHeartbeatCheck:
Girish Kumar2ad402b2020-03-20 19:45:12 +00001801 logger.Debug("Stopping heart beat check")
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301802 return
1803 }
1804 }
1805}
1806
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001807func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1808 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1809 if err != nil || device == nil {
1810 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1811 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301812
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001813 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1814 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1815 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1816 }
1817 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1818 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1819 }
1820 go dh.cleanupDeviceResources(ctx)
1821
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001822 dh.lockDevice.RLock()
1823 // Stop the read indication only if it the routine is active
1824 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1825 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1826 // on next execution of the readIndication routine.
1827 if dh.isReadIndicationRoutineActive {
1828 dh.stopIndications <- true
1829 }
1830 dh.lockDevice.RUnlock()
1831
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001832 dh.transitionMap.Handle(ctx, DeviceInit)
1833
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301834 }
1835}
kesavand39e0aa32020-01-28 20:58:50 -05001836
1837// EnablePort to enable Pon interface
1838func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001839 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001840 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001841}
1842
1843// DisablePort to disable pon interface
1844func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001845 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001846 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001847}
1848
kdarapu1afeceb2020-02-12 01:38:09 -05001849//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1850func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301851 ctx := context.Background()
Girish Kumar2ad402b2020-03-20 19:45:12 +00001852 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort})
kesavand39e0aa32020-01-28 20:58:50 -05001853 if port.GetType() == voltha.Port_ETHERNET_NNI {
1854 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001855 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
kesavand39e0aa32020-01-28 20:58:50 -05001856 log.Fields{"Device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301857 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001858 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001859 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001860 }
1861 // fetch interfaceid from PortNo
1862 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1863 ponIntf := &oop.Interface{IntfId: ponID}
1864 var operStatus voltha.OperStatus_Types
1865 if enablePort {
1866 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301867 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001868
1869 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301870 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001871 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001872 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001873 }
1874 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001875 dh.activePorts.Store(ponID, true)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001876 logger.Infow("enabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001877 } else {
1878 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301879 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001880 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301881 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001882 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001883 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001884 }
1885 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001886 dh.activePorts.Store(ponID, false)
Girish Kumar2ad402b2020-03-20 19:45:12 +00001887 logger.Infow("disabled-pon-port", log.Fields{"out": out, "DeviceID": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001888 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001889 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 +05301890 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001891 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001892 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001893 }
1894 return nil
1895}
1896
kdarapu1afeceb2020-02-12 01:38:09 -05001897//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1898func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001899 cloned := proto.Clone(device).(*voltha.Device)
1900 // Disable the port and update the oper_port_status to core
1901 // if the Admin state of the port is disabled on reboot and re-enable device.
1902 for _, port := range cloned.Ports {
1903 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05001904 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301905 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001906 "device-id": dh.deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +00001907 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001908 }
1909 }
1910 }
1911 return nil
1912}
1913
1914//populateActivePorts to populate activePorts map
1915func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001916 logger.Info("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05001917 for _, port := range device.Ports {
1918 if port.Type == voltha.Port_ETHERNET_NNI {
1919 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001920 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05001921 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001922 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05001923 }
1924 }
1925 if port.Type == voltha.Port_PON_OLT {
1926 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001927 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05001928 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05001929 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05001930 }
1931 }
1932 }
1933}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001934
1935// ChildDeviceLost deletes ONU and clears pon resources related to it.
1936func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001937 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001938 IntfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
1939 onuKey := dh.formOnuKey(IntfID, onuID)
1940 onuDevice, ok := dh.onus.Load(onuKey)
1941 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05301942 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001943 log.Fields{
1944 "device-id": dh.deviceID,
1945 "onu-id": onuID,
1946 "interface-id": IntfID}, nil).Log()
1947 }
1948 var sn *oop.SerialNumber
1949 var err error
1950 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301951 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001952 log.Fields{
1953 "devicer-id": dh.deviceID,
1954 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
1955 }
1956 onu := &oop.Onu{IntfId: IntfID, OnuId: onuID, SerialNumber: sn}
1957 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301958 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001959 "device-id": dh.deviceID,
1960 "onu-id": onuID}, err).Log()
1961 }
1962 //clear PON resources associated with ONU
1963 var onuGemData []rsrcMgr.OnuGemInfo
Andrea Campanella668ea5f2020-03-31 13:51:06 +02001964 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[IntfID]; !ok {
1965 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001966 "device-id": dh.deviceID,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02001967 "interface-id": IntfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05001968 } else {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02001969 if err := onuMgr.GetOnuGemInfo(ctx, IntfID, &onuGemData); err != nil {
1970 logger.Warnw("failed-to-get-onu-info-for-pon-port ", log.Fields{
1971 "device-id": dh.deviceID,
1972 "interface-id": IntfID,
1973 "error": err})
1974 } else {
1975 for i, onu := range onuGemData {
1976 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
1977 logger.Debugw("onu-data ", log.Fields{"onu": onu})
1978 if err := dh.clearUNIData(ctx, &onu); err != nil {
1979 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
1980 "device-id": dh.deviceID,
1981 "onu-device": onu,
1982 "error": err})
1983 }
1984 // Clear flowids for gem cache.
1985 for _, gem := range onu.GemPorts {
1986 dh.resourceMgr.DeleteFlowIDsForGem(ctx, IntfID, gem)
1987 }
1988 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
1989 err := onuMgr.AddOnuGemInfo(ctx, IntfID, onuGemData)
1990 if err != nil {
1991 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
1992 "interface-id": IntfID,
1993 "onu-device": onu,
1994 "onu-gem": onuGemData,
1995 "error": err})
1996 //Not returning error on cleanup.
1997 }
1998 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": IntfID, "onu-device": onu, "onugem": onuGemData})
1999 dh.resourceMgr.FreeonuID(ctx, IntfID, []uint32{onu.OnuID})
2000 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002001 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002002 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002003 }
2004 }
2005 dh.onus.Delete(onuKey)
2006 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2007 return nil
2008}
Girish Gowdracefae192020-03-19 18:14:10 -07002009
2010func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2011 for _, field := range flows.GetOfbFields(flow) {
2012 if field.Type == flows.IN_PORT {
2013 return field.GetPort()
2014 }
2015 }
2016 return InvalidPort
2017}
2018
2019func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2020 for _, action := range flows.GetActions(flow) {
2021 if action.Type == flows.OUTPUT {
2022 if out := action.GetOutput(); out != nil {
2023 return out.GetPort()
2024 }
2025 }
2026 }
2027 return InvalidPort
2028}
2029
2030func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2031 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002032 logger.Debugw("increment flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002033 if inPort != InvalidPort && outPort != InvalidPort {
2034 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2035 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002036 logger.Debugw("increment flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002037
2038 dh.lockDevice.Lock()
2039 defer dh.lockDevice.Unlock()
2040 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2041 if !ok {
2042 flowRemoveData = pendingFlowRemoveData{
2043 pendingFlowRemoveCount: 0,
2044 allFlowsRemoved: make(chan struct{}),
2045 }
2046 }
2047 flowRemoveData.pendingFlowRemoveCount++
2048 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2049
Girish Kumar2ad402b2020-03-20 19:45:12 +00002050 logger.Debugw("current flow remove count after increment",
Girish Gowdracefae192020-03-19 18:14:10 -07002051 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2052 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2053 }
2054}
2055
2056func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2057 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002058 logger.Debugw("decrement flow remove count for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002059 if inPort != InvalidPort && outPort != InvalidPort {
2060 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2061 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002062 logger.Debugw("decrement flow remove count for subscriber", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002063
2064 dh.lockDevice.Lock()
2065 defer dh.lockDevice.Unlock()
2066 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002067 logger.Fatalf("flow remove key not found", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002068 } else {
2069 if val.pendingFlowRemoveCount > 0 {
2070 val.pendingFlowRemoveCount--
2071 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00002072 logger.Debugw("current flow remove count after decrement",
Girish Gowdracefae192020-03-19 18:14:10 -07002073 log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID,
2074 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2075 // If all flow removes have finished, then close the channel to signal the receiver
2076 // to go ahead with flow adds.
2077 if val.pendingFlowRemoveCount == 0 {
2078 close(val.allFlowsRemoved)
2079 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2080 return
2081 }
2082 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2083 }
2084 }
2085}
2086
2087func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2088 var flowRemoveData pendingFlowRemoveData
2089 var ok bool
2090 inPort, outPort := getPorts(flow)
Girish Kumar2ad402b2020-03-20 19:45:12 +00002091 logger.Debugw("wait for flow remove to finish for inPort outPort", log.Fields{"inPort": inPort, "outPort": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002092 if inPort != InvalidPort && outPort != InvalidPort {
2093 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2094 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Girish Kumar2ad402b2020-03-20 19:45:12 +00002095 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 -07002096
2097 dh.lockDevice.RLock()
2098 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002099 logger.Debugw("no pending flow to remove", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002100 dh.lockDevice.RUnlock()
2101 return
2102 }
2103 dh.lockDevice.RUnlock()
2104
2105 // Wait for all flow removes to finish first
2106 <-flowRemoveData.allFlowsRemoved
2107
Girish Kumar2ad402b2020-03-20 19:45:12 +00002108 logger.Debugw("all flows cleared, handling flow add now", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002109 }
2110}
2111
2112func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2113 inPort := getInPortFromFlow(flow)
2114 outPort := getOutPortFromFlow(flow)
2115
2116 if inPort == InvalidPort || outPort == InvalidPort {
2117 return inPort, outPort
2118 }
2119
2120 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2121 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2122 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2123 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2124 return uniPort, outPort
2125 }
2126 }
2127 } else {
2128 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2129 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2130 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2131 return inPort, uniPort
2132 }
2133 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2134 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2135 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2136 return uniPort, outPort
2137 }
2138 }
2139 }
2140
2141 return InvalidPort, InvalidPort
2142}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002143
2144func extractOmciTransactionID(omciPkt []byte) uint16 {
2145 if len(omciPkt) > 3 {
2146 d := omciPkt[0:2]
2147 transid := binary.BigEndian.Uint16(d)
2148 return transid
2149 }
2150 return 0
2151}