blob: 7a818c5041c8d6b4ecc45106060aca259e5b8303 [file] [log] [blame]
Phaneendra Manda4c62c802019-03-06 21:37:49 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Phaneendra Manda4c62c802019-03-06 21:37:49 +053019
20import (
cuilin20187b2a8c32019-03-26 19:52:28 -070021 "context"
Matt Jeanneretceea2e02020-03-27 14:19:57 -040022 "encoding/binary"
Matt Jeanneret1359c732019-08-01 21:40:02 -040023 "encoding/hex"
cuilin20187b2a8c32019-03-26 19:52:28 -070024 "fmt"
25 "io"
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -040026 "net"
cuilin20187b2a8c32019-03-26 19:52:28 -070027 "strconv"
28 "strings"
29 "sync"
30 "time"
Phaneendra Manda4c62c802019-03-06 21:37:49 +053031
Shrey Baid807a2a02020-04-09 12:52:45 +053032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33
Matteo Scandolo945e4012019-12-12 14:16:11 -080034 "github.com/cenkalti/backoff/v3"
cuilin20187b2a8c32019-03-26 19:52:28 -070035 "github.com/gogo/protobuf/proto"
36 "github.com/golang/protobuf/ptypes"
Esin Karamanccb714b2019-11-29 15:02:06 +000037 "github.com/opencord/voltha-lib-go/v3/pkg/adapters/adapterif"
38 "github.com/opencord/voltha-lib-go/v3/pkg/log"
39 "github.com/opencord/voltha-lib-go/v3/pkg/pmmetrics"
Thomas Lee S94109f12020-03-03 16:39:29 +053040 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Scott Bakerdbd960e2020-02-28 08:57:51 -080041 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000042 "github.com/opencord/voltha-protos/v3/go/common"
43 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
44 of "github.com/opencord/voltha-protos/v3/go/openflow_13"
45 oop "github.com/opencord/voltha-protos/v3/go/openolt"
46 "github.com/opencord/voltha-protos/v3/go/voltha"
cuilin20187b2a8c32019-03-26 19:52:28 -070047 "google.golang.org/grpc"
Devmalya Paula1efa642020-04-20 01:36:43 -040048 "google.golang.org/grpc/codes"
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 {
cuilin20187b2a8c32019-03-26 19:52:28 -070076 device *voltha.Device
kdarapu381c6902019-07-31 18:23:16 +053077 coreProxy adapterif.CoreProxy
78 AdapterProxy adapterif.AdapterProxy
79 EventProxy adapterif.EventProxy
cuilin20187b2a8c32019-03-26 19:52:28 -070080 openOLT *OpenOLT
cuilin20187b2a8c32019-03-26 19:52:28 -070081 exitChannel chan int
82 lockDevice sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +053083 Client oop.OpenoltClient
cuilin20187b2a8c32019-03-26 19:52:28 -070084 transitionMap *TransitionMap
85 clientCon *grpc.ClientConn
manikkaraj kbf256be2019-03-25 00:13:48 +053086 flowMgr *OpenOltFlowMgr
Devmalya Paulfb990a52019-07-09 10:01:49 -040087 eventMgr *OpenOltEventMgr
manikkaraj kbf256be2019-03-25 00:13:48 +053088 resourceMgr *rsrcMgr.OpenOltResourceMgr
Naga Manjunatha8dc9372019-10-31 23:01:18 +053089
Girish Gowdra3ab6d212020-03-24 17:33:15 -070090 discOnus sync.Map
91 onus sync.Map
92 portStats *OpenOltStatisticsMgr
93 metrics *pmmetrics.PmMetrics
94 stopCollector chan bool
95 stopHeartbeatCheck chan bool
96 activePorts sync.Map
97 stopIndications chan bool
98 isReadIndicationRoutineActive bool
Girish Gowdracefae192020-03-19 18:14:10 -070099
100 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
101 // subscriber basis for the number of pending flow removes. This data is used
102 // to process all the flow removes for a subscriber before handling flow adds.
103 // Interleaving flow delete and flow add processing has known to cause PON resource
104 // management contentions on a per subscriber bases, so we need ensure ordering.
105 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700106}
107
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108//OnuDevice represents ONU related info
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700109type OnuDevice struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110 deviceID string
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700111 deviceType string
112 serialNumber string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 onuID uint32
114 intfID uint32
115 proxyDeviceID string
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530116 losRaised bool
Devmalya Paula1efa642020-04-20 01:36:43 -0400117 rdiRaised bool
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700118}
119
Naga Manjunath7615e552019-10-11 22:35:47 +0530120var pmNames = []string{
121 "rx_bytes",
122 "rx_packets",
123 "rx_mcast_packets",
124 "rx_bcast_packets",
125 "tx_bytes",
126 "tx_packets",
127 "tx_mcast_packets",
128 "tx_bcast_packets",
129}
130
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700131//NewOnuDevice creates a new Onu Device
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530132func NewOnuDevice(devID, deviceTp, serialNum string, onuID, intfID uint32, proxyDevID string, losRaised bool) *OnuDevice {
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700133 var device OnuDevice
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 device.deviceID = devID
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700135 device.deviceType = deviceTp
136 device.serialNumber = serialNum
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700137 device.onuID = onuID
138 device.intfID = intfID
139 device.proxyDeviceID = proxyDevID
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530140 device.losRaised = losRaised
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700141 return &device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530142}
143
144//NewDeviceHandler creates a new device handler
kdarapu381c6902019-07-31 18:23:16 +0530145func NewDeviceHandler(cp adapterif.CoreProxy, ap adapterif.AdapterProxy, ep adapterif.EventProxy, device *voltha.Device, adapter *OpenOLT) *DeviceHandler {
cuilin20187b2a8c32019-03-26 19:52:28 -0700146 var dh DeviceHandler
147 dh.coreProxy = cp
Girish Gowdru0c588b22019-04-23 23:24:56 -0400148 dh.AdapterProxy = ap
Devmalya Paulfb990a52019-07-09 10:01:49 -0400149 dh.EventProxy = ep
cuilin20187b2a8c32019-03-26 19:52:28 -0700150 cloned := (proto.Clone(device)).(*voltha.Device)
cuilin20187b2a8c32019-03-26 19:52:28 -0700151 dh.device = cloned
152 dh.openOLT = adapter
153 dh.exitChannel = make(chan int, 1)
154 dh.lockDevice = sync.RWMutex{}
Naga Manjunath7615e552019-10-11 22:35:47 +0530155 dh.stopCollector = make(chan bool, 2)
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +0530156 dh.stopHeartbeatCheck = make(chan bool, 2)
Naga Manjunath7615e552019-10-11 22:35:47 +0530157 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 -0500158 dh.activePorts = sync.Map{}
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400159 dh.stopIndications = make(chan bool, 1)
Girish Gowdracefae192020-03-19 18:14:10 -0700160 dh.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
161
cuilin20187b2a8c32019-03-26 19:52:28 -0700162 //TODO initialize the support classes.
163 return &dh
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530164}
165
166// start save the device to the data model
167func (dh *DeviceHandler) start(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700168 dh.lockDevice.Lock()
169 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000170 logger.Debugw("starting-device-agent", log.Fields{"device": dh.device})
cuilin20187b2a8c32019-03-26 19:52:28 -0700171 // Add the initial device to the local model
Girish Kumar2ad402b2020-03-20 19:45:12 +0000172 logger.Debug("device-agent-started")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530173}
174
175// stop stops the device dh. Not much to do for now
176func (dh *DeviceHandler) stop(ctx context.Context) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700177 dh.lockDevice.Lock()
178 defer dh.lockDevice.Unlock()
Girish Kumar2ad402b2020-03-20 19:45:12 +0000179 logger.Debug("stopping-device-agent")
cuilin20187b2a8c32019-03-26 19:52:28 -0700180 dh.exitChannel <- 1
Girish Kumar2ad402b2020-03-20 19:45:12 +0000181 logger.Debug("device-agent-stopped")
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530182}
183
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400184func macifyIP(ip net.IP) string {
185 if len(ip) > 0 {
186 oct1 := strconv.FormatInt(int64(ip[12]), 16)
187 oct2 := strconv.FormatInt(int64(ip[13]), 16)
188 oct3 := strconv.FormatInt(int64(ip[14]), 16)
189 oct4 := strconv.FormatInt(int64(ip[15]), 16)
190 return fmt.Sprintf("00:00:%02v:%02v:%02v:%02v", oct1, oct2, oct3, oct4)
191 }
192 return ""
193}
194
195func generateMacFromHost(host string) (string, error) {
196 var genmac string
197 var addr net.IP
198 var ips []string
199 var err error
200
Girish Kumar2ad402b2020-03-20 19:45:12 +0000201 logger.Debugw("generating-mac-from-host", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400202
203 if addr = net.ParseIP(host); addr == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000204 logger.Debugw("looking-up-hostname", log.Fields{"host": host})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400205
206 if ips, err = net.LookupHost(host); err == nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000207 logger.Debugw("dns-result-ips", log.Fields{"ips": ips})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400208 if addr = net.ParseIP(ips[0]); addr == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000209 return "", olterrors.NewErrInvalidValue(log.Fields{"ip": ips[0]}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400210 }
211 genmac = macifyIP(addr)
Shrey Baid807a2a02020-04-09 12:52:45 +0530212 logger.Debugw("using-ip-as-mac",
213 log.Fields{"host": ips[0],
214 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400215 return genmac, nil
216 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000217 return "", olterrors.NewErrAdapter("cannot-resolve-hostname-to-ip", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400218 }
219
220 genmac = macifyIP(addr)
Shrey Baid807a2a02020-04-09 12:52:45 +0530221 logger.Debugw("using-ip-as-mac",
222 log.Fields{"host": host,
223 "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400224 return genmac, nil
225}
226
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530227func macAddressToUint32Array(mac string) []uint32 {
cuilin20187b2a8c32019-03-26 19:52:28 -0700228 slist := strings.Split(mac, ":")
229 result := make([]uint32, len(slist))
230 var err error
231 var tmp int64
232 for index, val := range slist {
233 if tmp, err = strconv.ParseInt(val, 16, 32); err != nil {
234 return []uint32{1, 2, 3, 4, 5, 6}
235 }
236 result[index] = uint32(tmp)
237 }
238 return result
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530239}
240
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700241//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 -0800242func GetportLabel(portNum uint32, portType voltha.Port_PortType) (string, error) {
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530243
David K. Bainbridge794735f2020-02-11 21:01:37 -0800244 switch portType {
245 case voltha.Port_ETHERNET_NNI:
246 return fmt.Sprintf("nni-%d", portNum), nil
247 case voltha.Port_PON_OLT:
248 return fmt.Sprintf("pon-%d", portNum), nil
cuilin20187b2a8c32019-03-26 19:52:28 -0700249 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800250
Girish Kumarf26e4882020-03-05 06:49:10 +0000251 return "", olterrors.NewErrInvalidValue(log.Fields{"port-type": portType}, nil)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530252}
253
David K. Bainbridge794735f2020-02-11 21:01:37 -0800254func (dh *DeviceHandler) addPort(intfID uint32, portType voltha.Port_PortType, state string) error {
Esin Karamanccb714b2019-11-29 15:02:06 +0000255 var operStatus common.OperStatus_Types
cuilin20187b2a8c32019-03-26 19:52:28 -0700256 if state == "up" {
257 operStatus = voltha.OperStatus_ACTIVE
kesavand39e0aa32020-01-28 20:58:50 -0500258 //populating the intfStatus map
Chaitrashree G Sef088112020-02-03 21:39:27 -0500259 dh.activePorts.Store(intfID, true)
cuilin20187b2a8c32019-03-26 19:52:28 -0700260 } else {
261 operStatus = voltha.OperStatus_DISCOVERED
Chaitrashree G Sef088112020-02-03 21:39:27 -0500262 dh.activePorts.Store(intfID, false)
cuilin20187b2a8c32019-03-26 19:52:28 -0700263 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700264 portNum := IntfIDToPortNo(intfID, portType)
Chaitrashree G Sc0878ec2020-05-21 04:59:53 -0400265 label, err := GetportLabel(intfID, portType)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800266 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000267 return olterrors.NewErrNotFound("port-label", log.Fields{"port-number": portNum, "port-type": portType}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400268 }
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500269
270 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
271 if err != nil || device == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000272 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500273 }
274 if device.Ports != nil {
275 for _, dPort := range device.Ports {
276 if dPort.Type == portType && dPort.PortNo == portNum {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000277 logger.Debug("port-already-exists-updating-oper-status-of-port")
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500278 if err := dh.coreProxy.PortStateUpdate(context.TODO(), dh.device.Id, portType, portNum, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530279 return olterrors.NewErrAdapter("failed-to-update-port-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800280 "device-id": dh.device.Id,
281 "port-type": portType,
282 "port-number": portNum,
Girish Kumarf26e4882020-03-05 06:49:10 +0000283 "oper-status": operStatus}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800284
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500285 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800286 return nil
Chaitrashree G Sded0a832020-01-09 20:21:48 -0500287 }
288 }
289 }
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700290 capacity := uint32(of.OfpPortFeatures_OFPPF_1GB_FD | of.OfpPortFeatures_OFPPF_FIBER)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400291 // Now create Port
292 port := &voltha.Port{
cuilin20187b2a8c32019-03-26 19:52:28 -0700293 PortNo: portNum,
294 Label: label,
295 Type: portType,
296 OperStatus: operStatus,
Girish Gowdra631ef3d2020-06-15 10:45:52 -0700297 OfpPort: &of.OfpPort{
298 HwAddr: macAddressToUint32Array(dh.device.MacAddress),
299 Config: 0,
300 State: uint32(of.OfpPortState_OFPPS_LIVE),
301 Curr: capacity,
302 Advertised: capacity,
303 Peer: capacity,
304 CurrSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
305 MaxSpeed: uint32(of.OfpPortFeatures_OFPPF_1GB_FD),
306 },
cuilin20187b2a8c32019-03-26 19:52:28 -0700307 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530308 logger.Debugw("sending-port-update-to-core", log.Fields{"port": port})
cuilin20187b2a8c32019-03-26 19:52:28 -0700309 // Synchronous call to update device - this method is run in its own go routine
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700310 if err := dh.coreProxy.PortCreated(context.TODO(), dh.device.Id, port); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000311 return olterrors.NewErrAdapter("error-creating-port", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800312 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000313 "port-type": portType}, err)
Girish Gowdru1110ef22019-06-24 11:17:59 -0400314 }
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530315 go dh.updateLocalDevice()
316 return nil
317}
318
319func (dh *DeviceHandler) updateLocalDevice() error {
320 dh.lockDevice.Lock()
321 defer dh.lockDevice.Unlock()
322 device, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
323 if err != nil || device == nil {
324 logger.Errorf("device", log.Fields{"device-id": dh.device.Id}, err)
325 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
326 }
327 dh.device = device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800328 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530329}
330
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700331// nolint: gocyclo
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530332// readIndications to read the indications from the OLT device
David K. Bainbridge794735f2020-02-11 21:01:37 -0800333func (dh *DeviceHandler) readIndications(ctx context.Context) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000334 defer logger.Debugw("indications-ended", log.Fields{"device-id": dh.device.Id})
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700335 defer func() {
336 dh.lockDevice.Lock()
337 dh.isReadIndicationRoutineActive = false
338 dh.lockDevice.Unlock()
339 }()
Girish Gowdra3f974912020-03-23 20:35:18 -0700340 indications, err := dh.startOpenOltIndicationStream(ctx)
cuilin20187b2a8c32019-03-26 19:52:28 -0700341 if err != nil {
Girish Gowdra3f974912020-03-23 20:35:18 -0700342 return err
cuilin20187b2a8c32019-03-26 19:52:28 -0700343 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400344 /* get device state */
npujarec5762e2020-01-01 14:08:48 +0530345 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400346 if err != nil || device == nil {
347 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000348 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400349 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -0400350
David Bainbridgef5879ca2019-12-13 21:17:54 +0000351 // Create an exponential backoff around re-enabling indications. The
352 // maximum elapsed time for the back off is set to 0 so that we will
353 // continue to retry. The max interval defaults to 1m, but is set
354 // here for code clarity
355 indicationBackoff := backoff.NewExponentialBackOff()
356 indicationBackoff.MaxElapsedTime = 0
357 indicationBackoff.MaxInterval = 1 * time.Minute
Girish Gowdra3f974912020-03-23 20:35:18 -0700358
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700359 dh.lockDevice.Lock()
360 dh.isReadIndicationRoutineActive = true
361 dh.lockDevice.Unlock()
362
Girish Gowdra3f974912020-03-23 20:35:18 -0700363Loop:
cuilin20187b2a8c32019-03-26 19:52:28 -0700364 for {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400365 select {
366 case <-dh.stopIndications:
Thomas Lee S985938d2020-05-04 11:40:41 +0530367 logger.Debugw("stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700368 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400369 default:
370 indication, err := indications.Recv()
371 if err == io.EOF {
Shrey Baid807a2a02020-04-09 12:52:45 +0530372 logger.Infow("eof-for-indications",
373 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530374 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400375 // Use an exponential back off to prevent getting into a tight loop
376 duration := indicationBackoff.NextBackOff()
377 if duration == backoff.Stop {
378 // If we reach a maximum then warn and reset the backoff
379 // timer and keep attempting.
Shrey Baid807a2a02020-04-09 12:52:45 +0530380 logger.Warnw("maximum-indication-backoff-reached--resetting-backoff-timer",
381 log.Fields{"max-indication-backoff": indicationBackoff.MaxElapsedTime,
Thomas Lee S985938d2020-05-04 11:40:41 +0530382 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400383 indicationBackoff.Reset()
384 }
David Bainbridge95a3fcf2020-06-09 10:49:31 -0700385
386 // On failure process a backoff timer while watching for stopIndications
387 // events
388 backoff := time.NewTimer(indicationBackoff.NextBackOff())
389 select {
390 case <-dh.stopIndications:
391 logger.Debugw("stopping-collecting-indications-for-olt", log.Fields{"deviceID:": dh.device.Id})
392 if !backoff.Stop() {
393 <-backoff.C
394 }
395 break Loop
396 case <-backoff.C:
397 // backoff expired continue
398 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700399 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
400 return err
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400401 }
402 continue
David Bainbridgef5879ca2019-12-13 21:17:54 +0000403 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530404 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +0530405 logger.Errorw("read-indication-error",
406 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530407 "device-id": dh.device.Id})
408 if device.AdminState == voltha.AdminState_DELETED {
Shrey Baid807a2a02020-04-09 12:52:45 +0530409 logger.Debug("device-deleted--stopping-the-read-indication-thread")
Girish Gowdra3f974912020-03-23 20:35:18 -0700410 break Loop
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400411 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700412 // Close the stream, and re-initialize it
413 if err = indications.CloseSend(); err != nil {
414 // Ok to ignore here, because we landed here due to a problem on the stream
415 // In all probability, the closeSend call may fail
Shrey Baid807a2a02020-04-09 12:52:45 +0530416 logger.Debugw("error-closing-send stream--error-ignored",
417 log.Fields{"err": err,
Thomas Lee S985938d2020-05-04 11:40:41 +0530418 "device-id": dh.device.Id})
Girish Gowdra3f974912020-03-23 20:35:18 -0700419 }
420 if indications, err = dh.startOpenOltIndicationStream(ctx); err != nil {
421 return err
422 }
423 // once we re-initialized the indication stream, continue to read indications
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400424 continue
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530425 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400426 // Reset backoff if we have a successful receive
427 indicationBackoff.Reset()
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400428 // When OLT is admin down, ignore all indications.
Thomas Lee S985938d2020-05-04 11:40:41 +0530429 if device.AdminState == voltha.AdminState_DISABLED && !isIndicationAllowedDuringOltAdminDown(indication) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530430 logger.Debugw("olt-is-admin-down, ignore indication",
431 log.Fields{"indication": indication,
Thomas Lee S985938d2020-05-04 11:40:41 +0530432 "device-id": dh.device.Id})
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400433 continue
Devmalya Paul495b94a2019-08-27 19:42:00 -0400434 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400435 dh.handleIndication(ctx, indication)
cuilin20187b2a8c32019-03-26 19:52:28 -0700436 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700437 }
Girish Gowdra3f974912020-03-23 20:35:18 -0700438 // Close the send stream
439 _ = indications.CloseSend() // Ok to ignore error, as we stopping the readIndication anyway
Girish Gowdra3ab6d212020-03-24 17:33:15 -0700440
Girish Gowdra3f974912020-03-23 20:35:18 -0700441 return nil
442}
443
444func (dh *DeviceHandler) startOpenOltIndicationStream(ctx context.Context) (oop.Openolt_EnableIndicationClient, error) {
445
446 indications, err := dh.Client.EnableIndication(ctx, new(oop.Empty))
447 if err != nil {
448 return nil, olterrors.NewErrCommunication("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
449 }
450 if indications == nil {
451 return nil, olterrors.NewErrInvalidValue(log.Fields{"indications": nil, "device-id": dh.device.Id}, nil).Log()
452 }
453
454 return indications, nil
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400455}
456
457// isIndicationAllowedDuringOltAdminDown returns true if the indication is allowed during OLT Admin down, else false
458func isIndicationAllowedDuringOltAdminDown(indication *oop.Indication) bool {
459 switch indication.Data.(type) {
460 case *oop.Indication_OltInd, *oop.Indication_IntfInd, *oop.Indication_IntfOperInd:
461 return true
462
463 default:
464 return false
465 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700466}
467
David K. Bainbridge794735f2020-02-11 21:01:37 -0800468func (dh *DeviceHandler) handleOltIndication(ctx context.Context, oltIndication *oop.OltIndication) error {
Daniele Rossi051466a2019-07-26 13:39:37 +0000469 raisedTs := time.Now().UnixNano()
Gamze Abakaa1a50522019-10-03 19:28:27 +0000470 if oltIndication.OperState == "up" && dh.transitionMap.currentDeviceState != deviceStateUp {
npujarec5762e2020-01-01 14:08:48 +0530471 dh.transitionMap.Handle(ctx, DeviceUpInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700472 } else if oltIndication.OperState == "down" {
npujarec5762e2020-01-01 14:08:48 +0530473 dh.transitionMap.Handle(ctx, DeviceDownInd)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700474 }
Daniele Rossi051466a2019-07-26 13:39:37 +0000475 // Send or clear Alarm
Thomas Lee S985938d2020-05-04 11:40:41 +0530476 if err := dh.eventMgr.oltUpDownIndication(oltIndication, dh.device.Id, raisedTs); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530477 return olterrors.NewErrAdapter("failed-indication", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530478 "device_id": dh.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800479 "indication": oltIndication,
Girish Kumarf26e4882020-03-05 06:49:10 +0000480 "timestamp": raisedTs}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 }
482 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700483}
484
David K. Bainbridge794735f2020-02-11 21:01:37 -0800485// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530486func (dh *DeviceHandler) handleIndication(ctx context.Context, indication *oop.Indication) {
Devmalya Paulfb990a52019-07-09 10:01:49 -0400487 raisedTs := time.Now().UnixNano()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700488 switch indication.Data.(type) {
489 case *oop.Indication_OltInd:
David K. Bainbridge794735f2020-02-11 21:01:37 -0800490 if err := dh.handleOltIndication(ctx, indication.GetOltInd()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530491 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "olt", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800492 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700493 case *oop.Indication_IntfInd:
494 intfInd := indication.GetIntfInd()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800495 go func() {
496 if err := dh.addPort(intfInd.GetIntfId(), voltha.Port_PON_OLT, intfInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530497 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800498 }
499 }()
Thomas Lee S985938d2020-05-04 11:40:41 +0530500 logger.Infow("received-interface-indication", log.Fields{"InterfaceInd": intfInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700501 case *oop.Indication_IntfOperInd:
502 intfOperInd := indication.GetIntfOperInd()
503 if intfOperInd.GetType() == "nni" {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800504 go func() {
505 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_ETHERNET_NNI, intfOperInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530506 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-nni", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800507 }
508 }()
npujarec5762e2020-01-01 14:08:48 +0530509 dh.resourceMgr.AddNNIToKVStore(ctx, intfOperInd.GetIntfId())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700510 } else if intfOperInd.GetType() == "pon" {
511 // TODO: Check what needs to be handled here for When PON PORT down, ONU will be down
512 // Handle pon port update
David K. Bainbridge794735f2020-02-11 21:01:37 -0800513 go func() {
514 if err := dh.addPort(intfOperInd.GetIntfId(), voltha.Port_PON_OLT, intfOperInd.GetOperState()); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530515 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "interface-oper-pon", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800516 }
517 }()
Thomas Lee S985938d2020-05-04 11:40:41 +0530518 go dh.eventMgr.oltIntfOperIndication(indication.GetIntfOperInd(), dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700519 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530520 logger.Infow("received-interface-oper-indication",
521 log.Fields{"interfaceOperInd": intfOperInd,
Thomas Lee S985938d2020-05-04 11:40:41 +0530522 "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700523 case *oop.Indication_OnuDiscInd:
524 onuDiscInd := indication.GetOnuDiscInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530525 logger.Infow("received-onu-discovery-indication", log.Fields{"OnuDiscInd": onuDiscInd, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700526 sn := dh.stringifySerialNumber(onuDiscInd.SerialNumber)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800527 go func() {
528 if err := dh.onuDiscIndication(ctx, onuDiscInd, sn); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530529 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu-discovery", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800530 }
531 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700532 case *oop.Indication_OnuInd:
533 onuInd := indication.GetOnuInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530534 logger.Infow("received-onu-indication", log.Fields{"OnuInd": onuInd, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800535 go func() {
536 if err := dh.onuIndication(onuInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530537 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "onu", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800538 }
539 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700540 case *oop.Indication_OmciInd:
541 omciInd := indication.GetOmciInd()
Matteo Scandolo92186242020-06-12 10:54:18 -0700542 logger.Debugw("received-omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800543 go func() {
544 if err := dh.omciIndication(omciInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530545 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "omci", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800546 }
547 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700548 case *oop.Indication_PktInd:
549 pktInd := indication.GetPktInd()
Matteo Scandolo92186242020-06-12 10:54:18 -0700550 logger.Debugw("received-packet-indication", log.Fields{
551 "intf-type": pktInd.IntfId,
552 "intf-id": pktInd.IntfId,
553 "gem-port-id": pktInd.GemportId,
554 "port-no": pktInd.PortNo,
555 "device-id": dh.device.Id,
556 })
557
558 if logger.V(log.DebugLevel) {
559 logger.Debugw("received-packet-indication-packet", log.Fields{
560 "intf-type": pktInd.IntfId,
561 "intf-id": pktInd.IntfId,
562 "gem-port-id": pktInd.GemportId,
563 "port-no": pktInd.PortNo,
564 "packet": hex.EncodeToString(pktInd.Pkt),
565 "device-id": dh.device.Id,
566 })
567 }
568
David K. Bainbridge794735f2020-02-11 21:01:37 -0800569 go func() {
570 if err := dh.handlePacketIndication(ctx, pktInd); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530571 olterrors.NewErrAdapter("handle-indication-error", log.Fields{"type": "packet", "device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800572 }
573 }()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700574 case *oop.Indication_PortStats:
575 portStats := indication.GetPortStats()
Naga Manjunath7615e552019-10-11 22:35:47 +0530576 go dh.portStats.PortStatisticsIndication(portStats, dh.resourceMgr.DevInfo.GetPonPorts())
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700577 case *oop.Indication_FlowStats:
578 flowStats := indication.GetFlowStats()
Thomas Lee S985938d2020-05-04 11:40:41 +0530579 logger.Infow("received-flow-stats", log.Fields{"FlowStats": flowStats, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700580 case *oop.Indication_AlarmInd:
581 alarmInd := indication.GetAlarmInd()
Thomas Lee S985938d2020-05-04 11:40:41 +0530582 logger.Infow("received-alarm-indication", log.Fields{"AlarmInd": alarmInd, "device-id": dh.device.Id})
583 go dh.eventMgr.ProcessEvents(alarmInd, dh.device.Id, raisedTs)
cuilin20187b2a8c32019-03-26 19:52:28 -0700584 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530585}
586
587// doStateUp handle the olt up indication and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530588func (dh *DeviceHandler) doStateUp(ctx context.Context) error {
Thomas Lee S85f37312020-04-03 17:06:12 +0530589 //starting the stat collector
590 go startCollector(dh)
591
Girish Gowdru0c588b22019-04-23 23:24:56 -0400592 // Synchronous call to update device state - this method is run in its own go routine
npujarec5762e2020-01-01 14:08:48 +0530593 if err := dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_REACHABLE,
Girish Gowdru0c588b22019-04-23 23:24:56 -0400594 voltha.OperStatus_ACTIVE); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000595 return olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400596 }
597 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530598}
599
600// doStateDown handle the olt down indication
npujarec5762e2020-01-01 14:08:48 +0530601func (dh *DeviceHandler) doStateDown(ctx context.Context) error {
serkant.uluderya245caba2019-09-24 23:15:29 -0700602 dh.lockDevice.Lock()
603 defer dh.lockDevice.Unlock()
Thomas Lee S985938d2020-05-04 11:40:41 +0530604 logger.Debugw("do-state-down-start", log.Fields{"device-id": dh.device.Id})
Girish Gowdrud4245152019-05-10 00:47:31 -0400605
npujarec5762e2020-01-01 14:08:48 +0530606 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400607 if err != nil || device == nil {
608 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000609 return olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400610 }
611
612 cloned := proto.Clone(device).(*voltha.Device)
Girish Gowdrud4245152019-05-10 00:47:31 -0400613
614 //Update the device oper state and connection status
615 cloned.OperStatus = voltha.OperStatus_UNKNOWN
Girish Gowdrud4245152019-05-10 00:47:31 -0400616 dh.device = cloned
617
David K. Bainbridge794735f2020-02-11 21:01:37 -0800618 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000619 return olterrors.NewErrAdapter("state-update-failed", log.Fields{"device-id": device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400620 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400621
622 //get the child device for the parent device
npujarec5762e2020-01-01 14:08:48 +0530623 onuDevices, err := dh.coreProxy.GetChildDevices(ctx, dh.device.Id)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400624 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000625 return olterrors.NewErrAdapter("child-device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400626 }
627 for _, onuDevice := range onuDevices.Items {
628
629 // Update onu state as down in onu adapter
630 onuInd := oop.OnuIndication{}
631 onuInd.OperState = "down"
David K. Bainbridge794735f2020-02-11 21:01:37 -0800632 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700633 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
David K. Bainbridge794735f2020-02-11 21:01:37 -0800634 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530635 olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800636 "source": "openolt",
637 "onu-indicator": onuInd,
638 "device-type": onuDevice.Type,
639 "device-id": onuDevice.Id}, err).LogAt(log.ErrorLevel)
serkant.uluderya245caba2019-09-24 23:15:29 -0700640 //Do not return here and continue to process other ONUs
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700641 }
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -0400642 }
serkant.uluderya245caba2019-09-24 23:15:29 -0700643 /* Discovered ONUs entries need to be cleared , since after OLT
644 is up, it starts sending discovery indications again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530645 dh.discOnus = sync.Map{}
Girish Kumar2ad402b2020-03-20 19:45:12 +0000646 logger.Debugw("do-state-down-end", log.Fields{"device-id": device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700647 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530648}
649
650// doStateInit dial the grpc before going to init state
npujarec5762e2020-01-01 14:08:48 +0530651func (dh *DeviceHandler) doStateInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400652 var err error
David K. Bainbridge794735f2020-02-11 21:01:37 -0800653 if dh.clientCon, err = grpc.Dial(dh.device.GetHostAndPort(), grpc.WithInsecure(), grpc.WithBlock()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530654 return olterrors.NewErrCommunication("dial-failure", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530655 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000656 "host-and-port": dh.device.GetHostAndPort()}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400657 }
658 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530659}
660
661// postInit create olt client instance to invoke RPC on the olt device
npujarec5762e2020-01-01 14:08:48 +0530662func (dh *DeviceHandler) postInit(ctx context.Context) error {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400663 dh.Client = oop.NewOpenoltClient(dh.clientCon)
npujarec5762e2020-01-01 14:08:48 +0530664 dh.transitionMap.Handle(ctx, GrpcConnected)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400665 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530666}
667
668// doStateConnected get the device info and update to voltha core
npujarec5762e2020-01-01 14:08:48 +0530669func (dh *DeviceHandler) doStateConnected(ctx context.Context) error {
Thomas Lee S985938d2020-05-04 11:40:41 +0530670 var err error
671 logger.Debugw("olt-device-connected", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400672
673 // Case where OLT is disabled and then rebooted.
Thomas Lee S985938d2020-05-04 11:40:41 +0530674 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
675 if err != nil || device == nil {
676 /*TODO: needs to handle error scenarios */
677 return olterrors.NewErrAdapter("device-fetch-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
678 }
679 if device.AdminState == voltha.AdminState_DISABLED {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000680 logger.Debugln("do-state-connected--device-admin-state-down")
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400681
682 cloned := proto.Clone(device).(*voltha.Device)
683 cloned.ConnectStatus = voltha.ConnectStatus_REACHABLE
684 cloned.OperStatus = voltha.OperStatus_UNKNOWN
685 dh.device = cloned
Thomas Lee S985938d2020-05-04 11:40:41 +0530686 if err = dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
687 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400688 }
689
Chaitrashree G S44124192019-08-07 20:21:36 -0400690 // 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 +0530691 _, err = dh.Client.DisableOlt(ctx, new(oop.Empty))
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400692 if err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530693 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400694 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400695 // We should still go ahead an initialize various device handler modules so that when OLT is re-enabled, we have
696 // all the modules initialized and ready to handle incoming ONUs.
697
Thomas Lee S985938d2020-05-04 11:40:41 +0530698 err = dh.initializeDeviceHandlerModules(ctx)
699 if err != nil {
700 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400701 }
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400702
703 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800704 go func() {
Thomas Lee S985938d2020-05-04 11:40:41 +0530705 if err = dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530706 olterrors.NewErrAdapter("indication-read-failure", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800707 }
708 }()
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -0400709 return nil
710 }
711
Thomas Lee S985938d2020-05-04 11:40:41 +0530712 device, err = dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, dh.device.Id)
Girish Gowdrud4245152019-05-10 00:47:31 -0400713 if err != nil || device == nil {
714 /*TODO: needs to handle error scenarios */
Girish Kumarf26e4882020-03-05 06:49:10 +0000715 return olterrors.NewErrAdapter("fetch-device-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400716 }
kesavand39e0aa32020-01-28 20:58:50 -0500717 dh.populateActivePorts(device)
kdarapu1afeceb2020-02-12 01:38:09 -0500718 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000719 return olterrors.NewErrAdapter("port-status-update-failed", log.Fields{"device": device}, err)
Girish Gowdrud4245152019-05-10 00:47:31 -0400720 }
721
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400722 if err := dh.initializeDeviceHandlerModules(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +0530723 return olterrors.NewErrAdapter("device-handler-initialization-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
Girish Gowdru0c588b22019-04-23 23:24:56 -0400724 }
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530725
cuilin20187b2a8c32019-03-26 19:52:28 -0700726 // Start reading indications
David K. Bainbridge794735f2020-02-11 21:01:37 -0800727 go func() {
728 if err := dh.readIndications(ctx); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530729 olterrors.NewErrAdapter("read-indications-failure", log.Fields{"device-id": dh.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -0800730 }
731 }()
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530732 go dh.updateLocalDevice()
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000733
734 if device.PmConfigs != nil {
735 dh.UpdatePmConfig(device.PmConfigs)
736 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700737 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530738}
739
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400740func (dh *DeviceHandler) initializeDeviceHandlerModules(ctx context.Context) error {
741 deviceInfo, err := dh.populateDeviceInfo()
742
743 if err != nil {
744 return olterrors.NewErrAdapter("populate-device-info-failed", log.Fields{"device-id": dh.device.Id}, err)
745 }
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400746 // Instantiate resource manager
Neha Sharma3f221ae2020-04-29 19:02:12 +0000747 if dh.resourceMgr = rsrcMgr.NewResourceMgr(ctx, dh.device.Id, dh.openOLT.KVStoreAddress, dh.openOLT.KVStoreType, dh.device.Type, deviceInfo); dh.resourceMgr == nil {
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400748 return olterrors.ErrResourceManagerInstantiating
749 }
750
751 // Instantiate flow manager
752 if dh.flowMgr = NewFlowManager(ctx, dh, dh.resourceMgr); dh.flowMgr == nil {
753 return olterrors.ErrResourceManagerInstantiating
754
755 }
756 /* TODO: Instantiate Alarm , stats , BW managers */
757 /* Instantiating Event Manager to handle Alarms and KPIs */
758 dh.eventMgr = NewEventMgr(dh.EventProxy, dh)
759
760 // Stats config for new device
761 dh.portStats = NewOpenOltStatsMgr(dh)
762
763 return nil
764
765}
766
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400767func (dh *DeviceHandler) populateDeviceInfo() (*oop.DeviceInfo, error) {
768 var err error
769 var deviceInfo *oop.DeviceInfo
770
771 deviceInfo, err = dh.Client.GetDeviceInfo(context.Background(), new(oop.Empty))
772
773 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000774 return nil, olterrors.NewErrPersistence("get", "device", 0, nil, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400775 }
776 if deviceInfo == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000777 return nil, olterrors.NewErrInvalidValue(log.Fields{"device": nil}, nil)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400778 }
779
Thomas Lee S985938d2020-05-04 11:40:41 +0530780 logger.Debugw("fetched-device-info", log.Fields{"deviceInfo": deviceInfo, "device-id": dh.device.Id})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400781 dh.device.Root = true
782 dh.device.Vendor = deviceInfo.Vendor
783 dh.device.Model = deviceInfo.Model
784 dh.device.SerialNumber = deviceInfo.DeviceSerialNumber
785 dh.device.HardwareVersion = deviceInfo.HardwareVersion
786 dh.device.FirmwareVersion = deviceInfo.FirmwareVersion
787
788 if deviceInfo.DeviceId == "" {
Girish Kumar2ad402b2020-03-20 19:45:12 +0000789 logger.Warnw("no-device-id-provided-using-host", log.Fields{"hostport": dh.device.GetHostAndPort()})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400790 host := strings.Split(dh.device.GetHostAndPort(), ":")[0]
791 genmac, err := generateMacFromHost(host)
792 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000793 return nil, olterrors.NewErrAdapter("failed-to-generate-mac-host", log.Fields{"host": host}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400794 }
Girish Kumar2ad402b2020-03-20 19:45:12 +0000795 logger.Debugw("using-host-for-mac-address", log.Fields{"host": host, "mac": genmac})
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400796 dh.device.MacAddress = genmac
797 } else {
798 dh.device.MacAddress = deviceInfo.DeviceId
799 }
800
801 // Synchronous call to update device - this method is run in its own go routine
802 if err := dh.coreProxy.DeviceUpdate(context.TODO(), dh.device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000803 return nil, olterrors.NewErrAdapter("device-update-failed", log.Fields{"device-id": dh.device.Id}, err)
Matt Jeanneretf4fdcd72019-07-19 20:03:23 -0400804 }
805
806 return deviceInfo, nil
807}
808
Naga Manjunath7615e552019-10-11 22:35:47 +0530809func startCollector(dh *DeviceHandler) {
Shrey Baid807a2a02020-04-09 12:52:45 +0530810 logger.Debugf("starting-collector")
Naga Manjunath7615e552019-10-11 22:35:47 +0530811 for {
812 select {
813 case <-dh.stopCollector:
Thomas Lee S985938d2020-05-04 11:40:41 +0530814 logger.Debugw("stopping-collector-for-olt", log.Fields{"deviceID:": dh.device.Id})
Naga Manjunath7615e552019-10-11 22:35:47 +0530815 return
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000816 case <-time.After(time.Duration(dh.metrics.ToPmConfigs().DefaultFreq) * time.Second):
Girish Gowdra34815db2020-05-11 17:18:04 -0700817
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530818 ports := make([]*voltha.Port, len(dh.device.Ports))
819 copy(ports, dh.device.Ports)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530820 for _, port := range ports {
821 // NNI Stats
822 if port.Type == voltha.Port_ETHERNET_NNI {
823 intfID := PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI)
824 cmnni := dh.portStats.collectNNIMetrics(intfID)
825 logger.Debugw("collect-nni-metrics", log.Fields{"metrics": cmnni})
Girish Gowdra34815db2020-05-11 17:18:04 -0700826 go dh.portStats.publishMetrics(cmnni, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530827 logger.Debugw("publish-nni-metrics", log.Fields{"nni-port": port.Label})
828 }
829 // PON Stats
830 if port.Type == voltha.Port_PON_OLT {
831 intfID := PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT)
832 if val, ok := dh.activePorts.Load(intfID); ok && val == true {
833 cmpon := dh.portStats.collectPONMetrics(intfID)
834 logger.Debugw("collect-pon-metrics", log.Fields{"metrics": cmpon})
Girish Gowdra34815db2020-05-11 17:18:04 -0700835 go dh.portStats.publishMetrics(cmpon, port, dh.device.Id, dh.device.Type)
Kishore Darapuaaf9c102020-05-04 13:06:57 +0530836 }
837 logger.Debugw("publish-pon-metrics", log.Fields{"pon-port": port.Label})
Chaitrashree G Sef088112020-02-03 21:39:27 -0500838 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530839 }
840 }
841 }
842}
843
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700844//AdoptDevice adopts the OLT device
npujarec5762e2020-01-01 14:08:48 +0530845func (dh *DeviceHandler) AdoptDevice(ctx context.Context, device *voltha.Device) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400846 dh.transitionMap = NewTransitionMap(dh)
Shrey Baid807a2a02020-04-09 12:52:45 +0530847 logger.Infow("adopt-device", log.Fields{"device-id": device.Id, "Address": device.GetHostAndPort()})
npujarec5762e2020-01-01 14:08:48 +0530848 dh.transitionMap.Handle(ctx, DeviceInit)
Naga Manjunath7615e552019-10-11 22:35:47 +0530849
850 // Now, set the initial PM configuration for that device
851 if err := dh.coreProxy.DevicePMConfigUpdate(nil, dh.metrics.ToPmConfigs()); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530852 olterrors.NewErrAdapter("error-updating-performance-metrics", log.Fields{"device-id": device.Id}, err).LogAt(log.ErrorLevel)
Naga Manjunath7615e552019-10-11 22:35:47 +0530853 }
854
Chaitrashree G Sa4649252020-03-11 21:24:11 -0400855 go startHeartbeatCheck(ctx, dh)
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530856}
857
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700858//GetOfpDeviceInfo Gets the Ofp information of the given device
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530859func (dh *DeviceHandler) GetOfpDeviceInfo(device *voltha.Device) (*ic.SwitchCapability, error) {
cuilin20187b2a8c32019-03-26 19:52:28 -0700860 return &ic.SwitchCapability{
861 Desc: &of.OfpDesc{
Devmalya Paul70dd4972019-06-10 15:19:17 +0530862 MfrDesc: "VOLTHA Project",
cuilin20187b2a8c32019-03-26 19:52:28 -0700863 HwDesc: "open_pon",
864 SwDesc: "open_pon",
865 SerialNum: dh.device.SerialNumber,
866 },
867 SwitchFeatures: &of.OfpSwitchFeatures{
868 NBuffers: 256,
869 NTables: 2,
870 Capabilities: uint32(of.OfpCapabilities_OFPC_FLOW_STATS |
871 of.OfpCapabilities_OFPC_TABLE_STATS |
872 of.OfpCapabilities_OFPC_PORT_STATS |
873 of.OfpCapabilities_OFPC_GROUP_STATS),
874 },
875 }, nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530876}
877
David K. Bainbridge794735f2020-02-11 21:01:37 -0800878func (dh *DeviceHandler) omciIndication(omciInd *oop.OmciIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -0700879 logger.Debugw("omci-indication", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700880 var deviceType string
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700881 var deviceID string
882 var proxyDeviceID string
cuilin20187b2a8c32019-03-26 19:52:28 -0700883
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400884 transid := extractOmciTransactionID(omciInd.Pkt)
Matteo Scandolo92186242020-06-12 10:54:18 -0700885 if logger.V(log.DebugLevel) {
886 logger.Debugw("recv-omci-msg", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id,
887 "omci-transaction-id": transid, "omci-msg": hex.EncodeToString(omciInd.Pkt)})
888 }
Matt Jeanneretceea2e02020-03-27 14:19:57 -0400889
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700890 onuKey := dh.formOnuKey(omciInd.IntfId, omciInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530891
892 if onuInCache, ok := dh.onus.Load(onuKey); !ok {
893
Matteo Scandolo92186242020-06-12 10:54:18 -0700894 logger.Debugw("omci-indication-for-a-device-not-in-cache.", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700895 ponPort := IntfIDToPortNo(omciInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700896 kwargs := make(map[string]interface{})
897 kwargs["onu_id"] = omciInd.OnuId
898 kwargs["parent_port_no"] = ponPort
cuilin20187b2a8c32019-03-26 19:52:28 -0700899
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700900 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
901 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530902 return olterrors.NewErrNotFound("onu", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700903 "intf-id": omciInd.IntfId,
904 "onu-id": omciInd.OnuId}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700905 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700906 deviceType = onuDevice.Type
907 deviceID = onuDevice.Id
908 proxyDeviceID = onuDevice.ProxyAddress.DeviceId
909 //if not exist in cache, then add to cache.
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +0530910 dh.onus.Store(onuKey, NewOnuDevice(deviceID, deviceType, onuDevice.SerialNumber, omciInd.OnuId, omciInd.IntfId, proxyDeviceID, false))
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700911 } else {
912 //found in cache
Matteo Scandolo92186242020-06-12 10:54:18 -0700913 logger.Debugw("omci-indication-for-a-device-in-cache.", log.Fields{"intf-id": omciInd.IntfId, "onu-id": omciInd.OnuId, "device-id": dh.device.Id})
Naga Manjunatha8dc9372019-10-31 23:01:18 +0530914 deviceType = onuInCache.(*OnuDevice).deviceType
915 deviceID = onuInCache.(*OnuDevice).deviceID
916 proxyDeviceID = onuInCache.(*OnuDevice).proxyDeviceID
cuilin20187b2a8c32019-03-26 19:52:28 -0700917 }
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700918
919 omciMsg := &ic.InterAdapterOmciMessage{Message: omciInd.Pkt}
David K. Bainbridge794735f2020-02-11 21:01:37 -0800920 if err := dh.AdapterProxy.SendInterAdapterMessage(context.Background(), omciMsg,
Thomas Lee S985938d2020-05-04 11:40:41 +0530921 ic.InterAdapterMessageType_OMCI_REQUEST, dh.device.Type, deviceType,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800922 deviceID, proxyDeviceID, ""); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530923 return olterrors.NewErrCommunication("omci-request", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +0530924 "source": dh.device.Type,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800925 "destination": deviceType,
926 "onu-id": deviceID,
Girish Kumarf26e4882020-03-05 06:49:10 +0000927 "proxy-device-id": proxyDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700928 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800929 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530930}
931
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700932//ProcessInterAdapterMessage sends the proxied messages to the target device
933// If the proxy address is not found in the unmarshalled message, it first fetches the onu device for which the message
934// is meant, and then send the unmarshalled omci message to this onu
935func (dh *DeviceHandler) ProcessInterAdapterMessage(msg *ic.InterAdapterMessage) error {
Shrey Baid807a2a02020-04-09 12:52:45 +0530936 logger.Debugw("process-inter-adapter-message", log.Fields{"msgID": msg.Header.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -0700937 if msg.Header.Type == ic.InterAdapterMessageType_OMCI_REQUEST {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700938 msgID := msg.Header.Id
cuilin20187b2a8c32019-03-26 19:52:28 -0700939 fromTopic := msg.Header.FromTopic
940 toTopic := msg.Header.ToTopic
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700941 toDeviceID := msg.Header.ToDeviceId
942 proxyDeviceID := msg.Header.ProxyDeviceId
cuilin20187b2a8c32019-03-26 19:52:28 -0700943
Shrey Baid807a2a02020-04-09 12:52:45 +0530944 logger.Debugw("omci-request-message-header", log.Fields{"msgID": msgID, "fromTopic": fromTopic, "toTopic": toTopic, "toDeviceID": toDeviceID, "proxyDeviceID": proxyDeviceID})
cuilin20187b2a8c32019-03-26 19:52:28 -0700945
946 msgBody := msg.GetBody()
947
948 omciMsg := &ic.InterAdapterOmciMessage{}
949 if err := ptypes.UnmarshalAny(msgBody, omciMsg); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000950 return olterrors.NewErrAdapter("cannot-unmarshal-omci-msg-body", log.Fields{"msgbody": msgBody}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -0700951 }
952
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700953 if omciMsg.GetProxyAddress() == nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700954 onuDevice, err := dh.coreProxy.GetDevice(context.TODO(), dh.device.Id, toDeviceID)
955 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530956 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800957 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000958 "onu-device-id": toDeviceID}, err)
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700959 }
Shrey Baid807a2a02020-04-09 12:52:45 +0530960 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 -0800961 if err := dh.sendProxiedMessage(onuDevice, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530962 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800963 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000964 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800965 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700966 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +0530967 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 -0800968 if err := dh.sendProxiedMessage(nil, omciMsg); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530969 return olterrors.NewErrCommunication("send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800970 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +0000971 "onu-device-id": toDeviceID}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800972 }
cuilin20187b2a8c32019-03-26 19:52:28 -0700973 }
974
975 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +0000976 return olterrors.NewErrInvalidValue(log.Fields{"inter-adapter-message-type": msg.Header.Type}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -0700977 }
978 return nil
Phaneendra Manda4c62c802019-03-06 21:37:49 +0530979}
980
David K. Bainbridge794735f2020-02-11 21:01:37 -0800981func (dh *DeviceHandler) sendProxiedMessage(onuDevice *voltha.Device, omciMsg *ic.InterAdapterOmciMessage) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700982 var intfID uint32
983 var onuID uint32
Esin Karamanccb714b2019-11-29 15:02:06 +0000984 var connectStatus common.ConnectStatus_Types
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700985 if onuDevice != nil {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700986 intfID = onuDevice.ProxyAddress.GetChannelId()
987 onuID = onuDevice.ProxyAddress.GetOnuId()
988 connectStatus = onuDevice.ConnectStatus
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700989 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700990 intfID = omciMsg.GetProxyAddress().GetChannelId()
991 onuID = omciMsg.GetProxyAddress().GetOnuId()
992 connectStatus = omciMsg.GetConnectStatus()
Mahir Gunyela3f9add2019-06-06 15:13:19 -0700993 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700994 if connectStatus != voltha.ConnectStatus_REACHABLE {
Matteo Scandolo92186242020-06-12 10:54:18 -0700995 logger.Debugw("onu-not-reachable--cannot-send-omci", log.Fields{"intf-id": intfID, "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800996
Thomas Lee S94109f12020-03-03 16:39:29 +0530997 return olterrors.NewErrCommunication("unreachable", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700998 "intf-id": intfID,
999 "onu-id": onuID}, nil)
cuilin20187b2a8c32019-03-26 19:52:28 -07001000 }
1001
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001002 // TODO: OpenOLT Agent oop.OmciMsg expects a hex encoded string for OMCI packets rather than the actual bytes.
1003 // Fix this in the agent and then we can pass byte array as Pkt: omciMsg.Message.
lcuie24ef182019-04-29 22:58:36 -07001004 var omciMessage *oop.OmciMsg
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001005 hexPkt := make([]byte, hex.EncodedLen(len(omciMsg.Message)))
1006 hex.Encode(hexPkt, omciMsg.Message)
1007 omciMessage = &oop.OmciMsg{IntfId: intfID, OnuId: onuID, Pkt: hexPkt}
1008
1009 // TODO: Below logging illustrates the "stringify" of the omci Pkt.
1010 // once above is fixed this log line can change to just use hex.EncodeToString(omciMessage.Pkt)
1011 transid := extractOmciTransactionID(omciMsg.Message)
Matteo Scandolo92186242020-06-12 10:54:18 -07001012 logger.Debugw("sent-omci-msg", log.Fields{"intf-id": intfID, "onu-id": onuID,
Matt Jeanneretceea2e02020-03-27 14:19:57 -04001013 "omciTransactionID": transid, "omciMsg": string(omciMessage.Pkt)})
cuilin20187b2a8c32019-03-26 19:52:28 -07001014
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001015 _, err := dh.Client.OmciMsgOut(context.Background(), omciMessage)
1016 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301017 return olterrors.NewErrCommunication("omci-send-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001018 "intf-id": intfID,
1019 "onu-id": onuID,
1020 "message": omciMessage}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001021 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001022 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001023}
1024
David K. Bainbridge794735f2020-02-11 21:01:37 -08001025func (dh *DeviceHandler) activateONU(ctx context.Context, intfID uint32, onuID int64, serialNum *oop.SerialNumber, serialNumber string) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001026 logger.Debugw("activate-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "serialNum": serialNum, "serialNumber": serialNumber, "device-id": dh.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001027 if err := dh.flowMgr.UpdateOnuInfo(ctx, intfID, uint32(onuID), serialNumber); err != nil {
Matteo Scandolo92186242020-06-12 10:54:18 -07001028 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": onuID, "intf-id": intfID}, err)
Andrea Campanellab83b39d2020-03-30 11:41:16 +02001029 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001030 // TODO: need resource manager
1031 var pir uint32 = 1000000
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001032 Onu := oop.Onu{IntfId: intfID, OnuId: uint32(onuID), SerialNumber: serialNum, Pir: pir}
npujarec5762e2020-01-01 14:08:48 +05301033 if _, err := dh.Client.ActivateOnu(ctx, &Onu); err != nil {
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001034 st, _ := status.FromError(err)
1035 if st.Code() == codes.AlreadyExists {
Matteo Scandolo92186242020-06-12 10:54:18 -07001036 logger.Debugw("onu-activation-in-progress", log.Fields{"SerialNumber": serialNumber, "onu-id": onuID, "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001037 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301038 return olterrors.NewErrAdapter("onu-activate-failed", log.Fields{"onu": Onu, "device-id": dh.device.Id}, err)
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001039 }
cuilin20187b2a8c32019-03-26 19:52:28 -07001040 } else {
Thomas Lee S985938d2020-05-04 11:40:41 +05301041 logger.Infow("activated-onu", log.Fields{"SerialNumber": serialNumber, "device-id": dh.device.Id})
cuilin20187b2a8c32019-03-26 19:52:28 -07001042 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001044}
1045
David K. Bainbridge794735f2020-02-11 21:01:37 -08001046func (dh *DeviceHandler) onuDiscIndication(ctx context.Context, onuDiscInd *oop.OnuDiscIndication, sn string) error {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001047
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001048 channelID := onuDiscInd.GetIntfId()
1049 parentPortNo := IntfIDToPortNo(onuDiscInd.GetIntfId(), voltha.Port_PON_OLT)
Matt Jeanneret53539512019-07-20 14:47:02 -04001050
Girish Kumar2ad402b2020-03-20 19:45:12 +00001051 logger.Infow("new-discovery-indication", log.Fields{"sn": sn})
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301052
cuilin20187b2a8c32019-03-26 19:52:28 -07001053 kwargs := make(map[string]interface{})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001054 if sn != "" {
1055 kwargs["serial_number"] = sn
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001056 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001057 return olterrors.NewErrInvalidValue(log.Fields{"serial-number": sn}, nil)
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001058 }
1059
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301060 var alarmInd oop.OnuAlarmIndication
1061 raisedTs := time.Now().UnixNano()
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001062 if _, loaded := dh.discOnus.LoadOrStore(sn, true); loaded {
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301063
1064 /* When PON cable disconnected and connected back from OLT, it was expected OnuAlarmIndication
1065 with "los_status: off" should be raised but BAL does not raise this Alarm hence manually sending
1066 OnuLosClear event on receiving OnuDiscoveryIndication for the Onu after checking whether
1067 OnuLosRaise event sent for it */
1068 dh.onus.Range(func(Onukey interface{}, onuInCache interface{}) bool {
1069 if onuInCache.(*OnuDevice).serialNumber == sn && onuInCache.(*OnuDevice).losRaised {
1070 if onuDiscInd.GetIntfId() != onuInCache.(*OnuDevice).intfID {
Shrey Baid807a2a02020-04-09 12:52:45 +05301071 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301072 "previousIntfId": onuInCache.(*OnuDevice).intfID,
1073 "currentIntfId": onuDiscInd.GetIntfId()})
1074 // TODO:: Should we need to ignore raising OnuLosClear event
1075 // when onu connected to different PON?
1076 }
1077 alarmInd.IntfId = onuInCache.(*OnuDevice).intfID
1078 alarmInd.OnuId = onuInCache.(*OnuDevice).onuID
1079 alarmInd.LosStatus = statusCheckOff
1080 go dh.eventMgr.onuAlarmIndication(&alarmInd, onuInCache.(*OnuDevice).deviceID, raisedTs)
1081 }
1082 return true
1083 })
1084
Girish Kumar2ad402b2020-03-20 19:45:12 +00001085 logger.Warnw("onu-sn-is-already-being-processed", log.Fields{"sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001086 return nil
Amit Ghoshe5c6a852020-02-10 15:09:46 +00001087 }
1088
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001089 var onuID uint32
Matteo Scandolo945e4012019-12-12 14:16:11 -08001090
1091 // check the ONU is already know to the OLT
1092 // NOTE the second time the ONU is discovered this should return a device
1093 onuDevice, err := dh.coreProxy.GetChildDevice(ctx, dh.device.Id, kwargs)
1094
1095 if err != nil {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001096 logger.Debugw("core-proxy-get-child-device-failed", log.Fields{"parentDevice": dh.device.Id, "err": err, "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001097 if e, ok := status.FromError(err); ok {
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001098 logger.Debugw("core-proxy-get-child-device-failed-with-code", log.Fields{"errCode": e.Code(), "sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001099 switch e.Code() {
1100 case codes.Internal:
1101 // this probably means NOT FOUND, so just create a new device
1102 onuDevice = nil
1103 case codes.DeadlineExceeded:
1104 // if the call times out, cleanup and exit
1105 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001106 return olterrors.NewErrTimeout("get-child-device", log.Fields{"device-id": dh.device.Id}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001107 }
1108 }
1109 }
1110
1111 if onuDevice == nil {
1112 // NOTE this should happen a single time, and only if GetChildDevice returns NotFound
Andrea Campanella8c9b4f62020-05-18 18:43:13 +02001113 logger.Debugw("creating-new-onu", log.Fields{"sn": sn})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001114 // we need to create a new ChildDevice
Matt Jeanneret53539512019-07-20 14:47:02 -04001115 ponintfid := onuDiscInd.GetIntfId()
1116 dh.lockDevice.Lock()
npujarec5762e2020-01-01 14:08:48 +05301117 onuID, err = dh.resourceMgr.GetONUID(ctx, ponintfid)
Matt Jeanneret53539512019-07-20 14:47:02 -04001118 dh.lockDevice.Unlock()
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001119
Girish Kumar2ad402b2020-03-20 19:45:12 +00001120 logger.Infow("creating-new-onu-got-onu-id", log.Fields{"sn": sn, "onuId": onuID})
Matteo Scandolo945e4012019-12-12 14:16:11 -08001121
1122 if err != nil {
1123 // if we can't create an ID in resource manager,
1124 // cleanup and exit
Matteo Scandolo945e4012019-12-12 14:16:11 -08001125 dh.discOnus.Delete(sn)
Girish Kumarf26e4882020-03-05 06:49:10 +00001126 return olterrors.NewErrAdapter("resource-manager-get-onu-id-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001127 "pon-intf-id": ponintfid,
1128 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001129 }
1130
1131 if onuDevice, err = dh.coreProxy.ChildDeviceDetected(context.TODO(), dh.device.Id, int(parentPortNo),
1132 "", int(channelID), string(onuDiscInd.SerialNumber.GetVendorId()), sn, int64(onuID)); err != nil {
Matteo Scandolo945e4012019-12-12 14:16:11 -08001133 dh.discOnus.Delete(sn)
1134 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 +05301135 return olterrors.NewErrAdapter("core-proxy-child-device-detected-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001136 "pon-intf-id": ponintfid,
1137 "serial-number": sn}, err)
Matteo Scandolo945e4012019-12-12 14:16:11 -08001138 }
Amit Ghosh75f0e292020-05-14 11:31:54 +01001139 dh.eventMgr.OnuDiscoveryIndication(onuDiscInd, dh.device.Id, onuDevice.Id, onuID, sn, time.Now().UnixNano())
Shrey Baid807a2a02020-04-09 12:52:45 +05301140 logger.Infow("onu-child-device-added",
1141 log.Fields{"onuDevice": onuDevice,
1142 "sn": sn,
Matteo Scandolo92186242020-06-12 10:54:18 -07001143 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301144 "device-id": dh.device.Id})
Chaitrashree G Sbe6ab942019-05-24 06:42:49 -04001145 }
Matteo Scandolo945e4012019-12-12 14:16:11 -08001146
1147 // we can now use the existing ONU Id
1148 onuID = onuDevice.ProxyAddress.OnuId
Mahir Gunyele77977b2019-06-27 05:36:22 -07001149 //Insert the ONU into cache to use in OnuIndication.
1150 //TODO: Do we need to remove this from the cache on ONU change, or wait for overwritten on next discovery.
Shrey Baid807a2a02020-04-09 12:52:45 +05301151 logger.Debugw("onu-discovery-indication-key-create",
Matteo Scandolo92186242020-06-12 10:54:18 -07001152 log.Fields{"onu-id": onuID,
Shrey Baid807a2a02020-04-09 12:52:45 +05301153 "intfId": onuDiscInd.GetIntfId(),
1154 "sn": sn})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001155 onuKey := dh.formOnuKey(onuDiscInd.GetIntfId(), onuID)
Matt Jeanneret53539512019-07-20 14:47:02 -04001156
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301157 onuDev := NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuID, onuDiscInd.GetIntfId(), onuDevice.ProxyAddress.DeviceId, false)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301158 dh.onus.Store(onuKey, onuDev)
Shrey Baid807a2a02020-04-09 12:52:45 +05301159 logger.Debugw("new-onu-device-discovered",
1160 log.Fields{"onu": onuDev,
1161 "sn": sn})
Chaitrashree G S35b5d802019-07-08 23:12:03 -04001162
David K. Bainbridge794735f2020-02-11 21:01:37 -08001163 if err = dh.coreProxy.DeviceStateUpdate(ctx, onuDevice.Id, common.ConnectStatus_REACHABLE, common.OperStatus_DISCOVERED); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301164 return olterrors.NewErrAdapter("failed-to-update-device-state", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001166 "serial-number": sn}, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001167 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301168 logger.Infow("onu-discovered-reachable", log.Fields{"device-id": onuDevice.Id, "sn": sn})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001169 if err = dh.activateONU(ctx, onuDiscInd.IntfId, int64(onuID), onuDiscInd.SerialNumber, sn); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301170 return olterrors.NewErrAdapter("onu-activation-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 "device-id": onuDevice.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001172 "serial-number": sn}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 }
1174 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001175}
1176
David K. Bainbridge794735f2020-02-11 21:01:37 -08001177func (dh *DeviceHandler) onuIndication(onuInd *oop.OnuIndication) error {
cuilin20187b2a8c32019-03-26 19:52:28 -07001178 serialNumber := dh.stringifySerialNumber(onuInd.SerialNumber)
1179
1180 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181 ponPort := IntfIDToPortNo(onuInd.GetIntfId(), voltha.Port_PON_OLT)
Mahir Gunyele77977b2019-06-27 05:36:22 -07001182 var onuDevice *voltha.Device
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 var err error
Mahir Gunyele77977b2019-06-27 05:36:22 -07001184 foundInCache := false
Shrey Baid807a2a02020-04-09 12:52:45 +05301185 logger.Debugw("onu-indication-key-create",
1186 log.Fields{"onuId": onuInd.OnuId,
1187 "intfId": onuInd.GetIntfId(),
Thomas Lee S985938d2020-05-04 11:40:41 +05301188 "device-id": dh.device.Id})
Mahir Gunyele77977b2019-06-27 05:36:22 -07001189 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.OnuId)
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301190
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 errFields := log.Fields{"device-id": dh.device.Id}
1192
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301193 if onuInCache, ok := dh.onus.Load(onuKey); ok {
1194
Mahir Gunyele77977b2019-06-27 05:36:22 -07001195 //If ONU id is discovered before then use GetDevice to get onuDevice because it is cheaper.
1196 foundInCache = true
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 errFields["onu-id"] = onuInCache.(*OnuDevice).deviceID
1198 onuDevice, err = dh.coreProxy.GetDevice(nil, dh.device.Id, onuInCache.(*OnuDevice).deviceID)
cuilin20187b2a8c32019-03-26 19:52:28 -07001199 } else {
Mahir Gunyele77977b2019-06-27 05:36:22 -07001200 //If ONU not found in adapter cache then we have to use GetChildDevice to get onuDevice
1201 if serialNumber != "" {
1202 kwargs["serial_number"] = serialNumber
David K. Bainbridge794735f2020-02-11 21:01:37 -08001203 errFields["serial-number"] = serialNumber
Mahir Gunyele77977b2019-06-27 05:36:22 -07001204 } else {
1205 kwargs["onu_id"] = onuInd.OnuId
1206 kwargs["parent_port_no"] = ponPort
David K. Bainbridge794735f2020-02-11 21:01:37 -08001207 errFields["onu-id"] = onuInd.OnuId
1208 errFields["parent-port-no"] = ponPort
Mahir Gunyele77977b2019-06-27 05:36:22 -07001209 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 onuDevice, err = dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
cuilin20187b2a8c32019-03-26 19:52:28 -07001211 }
Mahir Gunyele77977b2019-06-27 05:36:22 -07001212
David K. Bainbridge794735f2020-02-11 21:01:37 -08001213 if err != nil || onuDevice == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001214 return olterrors.NewErrNotFound("onu-device", errFields, err)
cuilin20187b2a8c32019-03-26 19:52:28 -07001215 }
1216
David K. Bainbridge794735f2020-02-11 21:01:37 -08001217 if onuDevice.ParentPortNo != ponPort {
Shrey Baid807a2a02020-04-09 12:52:45 +05301218 logger.Warnw("onu-is-on-a-different-intf-id-now", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001219 "previousIntfId": onuDevice.ParentPortNo,
1220 "currentIntfId": ponPort})
1221 }
1222
1223 if onuDevice.ProxyAddress.OnuId != onuInd.OnuId {
Shrey Baid807a2a02020-04-09 12:52:45 +05301224 logger.Warnw("onu-id-mismatch-possible-if-voltha-and-olt-rebooted", log.Fields{
1225 "expected-onu-id": onuDevice.ProxyAddress.OnuId,
1226 "received-onu-id": onuInd.OnuId,
Thomas Lee S985938d2020-05-04 11:40:41 +05301227 "device-id": dh.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001228 }
1229 if !foundInCache {
1230 onuKey := dh.formOnuKey(onuInd.GetIntfId(), onuInd.GetOnuId())
1231
Thiyagarajan Subramani34a00282020-03-10 20:19:31 +05301232 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 -08001233
1234 }
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001235 if err := dh.updateOnuStates(onuDevice, onuInd); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001236 return olterrors.NewErrCommunication("state-update-failed", errFields, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001237 }
1238 return nil
cuilin20187b2a8c32019-03-26 19:52:28 -07001239}
1240
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001241func (dh *DeviceHandler) updateOnuStates(onuDevice *voltha.Device, onuInd *oop.OnuIndication) error {
npujarec5762e2020-01-01 14:08:48 +05301242 ctx := context.TODO()
Shrey Baid807a2a02020-04-09 12:52:45 +05301243 logger.Debugw("onu-indication-for-state", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdraa6415dd2020-07-01 10:27:52 -07001244 if onuInd.AdminState == "down" || onuInd.OperState == "down" {
1245 // The ONU has gone admin_state "down" or oper_state "down" - we expect the ONU to send discovery again
1246 // The ONU admin_state is "up" while "oper_state" is down in cases where ONU activation fails. In this case
1247 // the ONU sends Discovery again.
Girish Gowdra429f9502020-05-04 13:22:16 -07001248 dh.discOnus.Delete(onuDevice.SerialNumber)
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001249 // Tests have shown that we sometimes get OperState as NOT down even if AdminState is down, forcing it
1250 if onuInd.OperState != "down" {
Shrey Baid807a2a02020-04-09 12:52:45 +05301251 logger.Warnw("onu-admin-state-down", log.Fields{"operState": onuInd.OperState})
Amit Ghosh9bbc5652020-02-17 13:37:32 +00001252 onuInd.OperState = "down"
1253 }
1254 }
1255
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 switch onuInd.OperState {
1257 case "down":
Shrey Baid807a2a02020-04-09 12:52:45 +05301258 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001259 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301260 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001261 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1262 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301263 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264 "onu-indicator": onuInd,
1265 "source": "openolt",
1266 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001267 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001268 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001269 case "up":
Shrey Baid807a2a02020-04-09 12:52:45 +05301270 logger.Debugw("sending-interadapter-onu-indication", log.Fields{"onuIndication": onuInd, "device-id": onuDevice.Id, "operStatus": onuDevice.OperStatus, "adminStatus": onuDevice.AdminState})
Matt Jeanneret53539512019-07-20 14:47:02 -04001271 // TODO NEW CORE do not hardcode adapter name. Handler needs Adapter reference
npujarec5762e2020-01-01 14:08:48 +05301272 err := dh.AdapterProxy.SendInterAdapterMessage(ctx, onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001273 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1274 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301275 return olterrors.NewErrCommunication("inter-adapter-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001276 "onu-indicator": onuInd,
1277 "source": "openolt",
1278 "device-type": onuDevice.Type,
Girish Kumarf26e4882020-03-05 06:49:10 +00001279 "device-id": onuDevice.Id}, err)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001280 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001282 return olterrors.NewErrInvalidValue(log.Fields{"oper-state": onuInd.OperState}, nil)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001283 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001285}
1286
cuilin20187b2a8c32019-03-26 19:52:28 -07001287func (dh *DeviceHandler) stringifySerialNumber(serialNum *oop.SerialNumber) string {
1288 if serialNum != nil {
1289 return string(serialNum.VendorId) + dh.stringifyVendorSpecific(serialNum.VendorSpecific)
cuilin20187b2a8c32019-03-26 19:52:28 -07001290 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001291 return ""
cuilin20187b2a8c32019-03-26 19:52:28 -07001292}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05001293func (dh *DeviceHandler) deStringifySerialNumber(serialNum string) (*oop.SerialNumber, error) {
1294 decodedStr, err := hex.DecodeString(serialNum[4:])
1295 if err != nil {
1296 return nil, err
1297 }
1298 return &oop.SerialNumber{
1299 VendorId: []byte(serialNum[:4]),
1300 VendorSpecific: []byte(decodedStr),
1301 }, nil
1302}
cuilin20187b2a8c32019-03-26 19:52:28 -07001303
1304func (dh *DeviceHandler) stringifyVendorSpecific(vendorSpecific []byte) string {
1305 tmp := fmt.Sprintf("%x", (uint32(vendorSpecific[0])>>4)&0x0f) +
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001306 fmt.Sprintf("%x", uint32(vendorSpecific[0]&0x0f)) +
cuilin20187b2a8c32019-03-26 19:52:28 -07001307 fmt.Sprintf("%x", (uint32(vendorSpecific[1])>>4)&0x0f) +
1308 fmt.Sprintf("%x", (uint32(vendorSpecific[1]))&0x0f) +
1309 fmt.Sprintf("%x", (uint32(vendorSpecific[2])>>4)&0x0f) +
1310 fmt.Sprintf("%x", (uint32(vendorSpecific[2]))&0x0f) +
1311 fmt.Sprintf("%x", (uint32(vendorSpecific[3])>>4)&0x0f) +
1312 fmt.Sprintf("%x", (uint32(vendorSpecific[3]))&0x0f)
1313 return tmp
1314}
1315
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001316//UpdateFlowsBulk upates the bulk flow
1317func (dh *DeviceHandler) UpdateFlowsBulk() error {
Thomas Lee S94109f12020-03-03 16:39:29 +05301318 return olterrors.ErrNotImplemented
cuilin20187b2a8c32019-03-26 19:52:28 -07001319}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001320
1321//GetChildDevice returns the child device for given parent port and onu id
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322func (dh *DeviceHandler) GetChildDevice(parentPort, onuID uint32) (*voltha.Device, error) {
Shrey Baid807a2a02020-04-09 12:52:45 +05301323 logger.Debugw("getchilddevice",
1324 log.Fields{"pon-port": parentPort,
Matteo Scandolo92186242020-06-12 10:54:18 -07001325 "onu-id": onuID,
Thomas Lee S985938d2020-05-04 11:40:41 +05301326 "device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001327 kwargs := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001328 kwargs["onu_id"] = onuID
Girish Gowdru0c588b22019-04-23 23:24:56 -04001329 kwargs["parent_port_no"] = parentPort
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001330 onuDevice, err := dh.coreProxy.GetChildDevice(context.TODO(), dh.device.Id, kwargs)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001331 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001332 return nil, olterrors.NewErrNotFound("onu-device", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001333 "intf-id": parentPort,
1334 "onu-id": onuID}, err)
Girish Gowdru0c588b22019-04-23 23:24:56 -04001335 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301336 logger.Debugw("successfully-received-child-device-from-core", log.Fields{"child-device-id": onuDevice.Id, "child-device-sn": onuDevice.SerialNumber})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001337 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301338}
1339
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001340// SendPacketInToCore sends packet-in to core
1341// For this, it calls SendPacketIn of the core-proxy which uses a device specific topic to send the request.
1342// The adapter handling the device creates a device specific topic
David K. Bainbridge794735f2020-02-11 21:01:37 -08001343func (dh *DeviceHandler) SendPacketInToCore(logicalPort uint32, packetPayload []byte) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001344 if logger.V(log.DebugLevel) {
1345 logger.Debugw("send-packet-in-to-core", log.Fields{
1346 "port": logicalPort,
1347 "packet": hex.EncodeToString(packetPayload),
1348 "device-id": dh.device.Id,
1349 })
1350 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001351 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPort, packetPayload); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301352 return olterrors.NewErrCommunication("packet-send-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001353 "source": "adapter",
1354 "destination": "core",
1355 "device-id": dh.device.Id,
1356 "logical-port": logicalPort,
Girish Kumarf26e4882020-03-05 06:49:10 +00001357 "packet": hex.EncodeToString(packetPayload)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001358 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001359 if logger.V(log.DebugLevel) {
1360 logger.Debugw("sent-packet-in-to-core-successfully", log.Fields{
1361 "packet": hex.EncodeToString(packetPayload),
1362 "device-id": dh.device.Id,
1363 })
1364 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001365 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001366}
1367
Rohan Agrawalda5e0b22020-05-20 11:10:26 +00001368// UpdatePmConfig updates the pm metrics.
1369func (dh *DeviceHandler) UpdatePmConfig(pmConfigs *voltha.PmConfigs) {
1370
1371 logger.Infow("update-pm-configs", log.Fields{"device-id": dh.device.Id, "pm-configs": pmConfigs})
1372
1373 if pmConfigs.DefaultFreq != dh.metrics.ToPmConfigs().DefaultFreq {
1374 dh.metrics.UpdateFrequency(pmConfigs.DefaultFreq)
1375 logger.Debugf("frequency-updated")
1376 }
1377
1378 if pmConfigs.Grouped == false {
1379 metrics := dh.metrics.GetSubscriberMetrics()
1380 for _, m := range pmConfigs.Metrics {
1381 metrics[m.Name].Enabled = m.Enabled
1382
1383 }
1384 }
1385}
1386
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001387//UpdateFlowsIncrementally updates the device flow
npujarec5762e2020-01-01 14:08:48 +05301388func (dh *DeviceHandler) UpdateFlowsIncrementally(ctx context.Context, device *voltha.Device, flows *of.FlowChanges, groups *of.FlowGroupChanges, flowMetadata *voltha.FlowMetadata) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301389 logger.Debugw("received-incremental-flowupdate-in-device-handler", log.Fields{"device-id": device.Id, "flows": flows, "groups": groups, "flowMetadata": flowMetadata})
Andrea Campanellac63bba92020-03-10 17:01:04 +01001390
1391 var errorsList []error
1392
Girish Gowdru0c588b22019-04-23 23:24:56 -04001393 if flows != nil {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001394 for _, flow := range flows.ToRemove.Items {
Girish Gowdracefae192020-03-19 18:14:10 -07001395 dh.incrementActiveFlowRemoveCount(flow)
1396
Shrey Baid807a2a02020-04-09 12:52:45 +05301397 logger.Debugw("removing-flow",
1398 log.Fields{"device-id": device.Id,
1399 "flowToRemove": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001400 err := dh.flowMgr.RemoveFlow(ctx, flow)
1401 if err != nil {
1402 errorsList = append(errorsList, err)
1403 }
1404
1405 dh.decrementActiveFlowRemoveCount(flow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001406 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301407
1408 for _, flow := range flows.ToAdd.Items {
Shrey Baid807a2a02020-04-09 12:52:45 +05301409 logger.Debugw("adding-flow",
1410 log.Fields{"device-id": device.Id,
1411 "flowToAdd": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07001412 // If there are active Flow Remove in progress for a given subscriber, wait until it completes
1413 dh.waitForFlowRemoveToFinish(flow)
Andrea Campanellac63bba92020-03-10 17:01:04 +01001414 err := dh.flowMgr.AddFlow(ctx, flow, flowMetadata)
1415 if err != nil {
1416 errorsList = append(errorsList, err)
1417 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301418 }
Girish Gowdru0c588b22019-04-23 23:24:56 -04001419 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001420
Girish Gowdracefae192020-03-19 18:14:10 -07001421 // 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 +00001422 if groups != nil {
1423 for _, group := range groups.ToAdd.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001424 err := dh.flowMgr.AddGroup(ctx, group)
1425 if err != nil {
1426 errorsList = append(errorsList, err)
1427 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001428 }
1429 for _, group := range groups.ToUpdate.Items {
Andrea Campanellac63bba92020-03-10 17:01:04 +01001430 err := dh.flowMgr.ModifyGroup(ctx, group)
1431 if err != nil {
1432 errorsList = append(errorsList, err)
1433 }
Esin Karamanccb714b2019-11-29 15:02:06 +00001434 }
1435 if len(groups.ToRemove.Items) != 0 {
Thomas Lee S985938d2020-05-04 11:40:41 +05301436 logger.Debugw("group-delete-operation-not-supported", log.Fields{"device-id": dh.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001437 }
1438 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01001439 if len(errorsList) > 0 {
1440 return fmt.Errorf("errors-installing-flows-groups, errors:%v", errorsList)
1441 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301442 logger.Debugw("updated-flows-incrementally-successfully", log.Fields{"device-id": dh.device.Id})
Girish Gowdru0c588b22019-04-23 23:24:56 -04001443 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301444}
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001445
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001446//DisableDevice disables the given device
1447//It marks the following for the given device:
1448//Device-Handler Admin-State : down
1449//Device Port-State: UNKNOWN
1450//Device Oper-State: UNKNOWN
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001451func (dh *DeviceHandler) DisableDevice(device *voltha.Device) error {
Chaitrashree G S44124192019-08-07 20:21:36 -04001452 /* On device disable ,admin state update has to be done prior sending request to agent since
1453 the indication thread may processes invalid indications of ONU and OLT*/
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001454 if dh.Client != nil {
1455 if _, err := dh.Client.DisableOlt(context.Background(), new(oop.Empty)); err != nil {
1456 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001457 return olterrors.NewErrAdapter("olt-disable-failed", log.Fields{"device-id": device.Id}, err)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001458 }
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001459 }
Chaitrashree G S44124192019-08-07 20:21:36 -04001460 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301461 logger.Debugw("olt-disabled", log.Fields{"device-id": device.Id})
Chaitrashree G S44124192019-08-07 20:21:36 -04001462 /* Discovered ONUs entries need to be cleared , since on device disable the child devices goes to
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001463 UNREACHABLE state which needs to be configured again*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301464
1465 dh.discOnus = sync.Map{}
1466 dh.onus = sync.Map{}
1467
Thomas Lee S85f37312020-04-03 17:06:12 +05301468 //stopping the stats collector
1469 dh.stopCollector <- true
1470
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301471 go dh.notifyChildDevices("unreachable")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001472 cloned := proto.Clone(device).(*voltha.Device)
Thomas Lee S985938d2020-05-04 11:40:41 +05301473 //Update device Admin state
1474 dh.device = cloned
kdarapu1afeceb2020-02-12 01:38:09 -05001475 // Update the all pon ports state on that device to disable and NNI remains active as NNI remains active in openolt agent.
1476 for _, port := range cloned.Ports {
1477 if port.GetType() == voltha.Port_PON_OLT {
1478 if err := dh.coreProxy.PortStateUpdate(context.TODO(), cloned.Id,
1479 voltha.Port_PON_OLT, port.GetPortNo(), voltha.OperStatus_UNKNOWN); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001480 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{"device-id": device.Id, "port-number": port.GetPortNo()}, err)
kdarapu1afeceb2020-02-12 01:38:09 -05001481 }
1482 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001483 }
1484
Shrey Baid807a2a02020-04-09 12:52:45 +05301485 logger.Debugw("disable-device-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001486 return nil
1487}
1488
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301489func (dh *DeviceHandler) notifyChildDevices(state string) {
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001490
1491 // Update onu state as unreachable in onu adapter
1492 onuInd := oop.OnuIndication{}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301493 onuInd.OperState = state
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001494 //get the child device for the parent device
1495 onuDevices, err := dh.coreProxy.GetChildDevices(context.TODO(), dh.device.Id)
1496 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301497 logger.Errorw("failed-to-get-child-devices-information", log.Fields{"device-id": dh.device.Id, "error": err})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001498 }
1499 if onuDevices != nil {
1500 for _, onuDevice := range onuDevices.Items {
1501 err := dh.AdapterProxy.SendInterAdapterMessage(context.TODO(), &onuInd, ic.InterAdapterMessageType_ONU_IND_REQUEST,
1502 "openolt", onuDevice.Type, onuDevice.Id, onuDevice.ProxyAddress.DeviceId, "")
1503 if err != nil {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001504 logger.Errorw("failed-to-send-inter-adapter-message", log.Fields{"OnuInd": onuInd,
Shrey Baid807a2a02020-04-09 12:52:45 +05301505 "From Adapter": "openolt", "DeviceType": onuDevice.Type, "device-id": onuDevice.Id})
Chaitrashree G S3b4c0352019-09-09 20:59:29 -04001506 }
1507
1508 }
1509 }
1510
1511}
1512
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001513//ReenableDevice re-enables the olt device after disable
1514//It marks the following for the given device:
1515//Device-Handler Admin-State : up
1516//Device Port-State: ACTIVE
1517//Device Oper-State: ACTIVE
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001518func (dh *DeviceHandler) ReenableDevice(device *voltha.Device) error {
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301519
1520 if _, err := dh.Client.ReenableOlt(context.Background(), new(oop.Empty)); err != nil {
1521 if e, ok := status.FromError(err); ok && e.Code() == codes.Internal {
Girish Kumarf26e4882020-03-05 06:49:10 +00001522 return olterrors.NewErrAdapter("olt-reenable-failed", log.Fields{"device-id": dh.device.Id}, err)
Abhilash Laxmeshwar5b302e12020-01-09 15:15:14 +05301523 }
1524 }
Girish Kumar2ad402b2020-03-20 19:45:12 +00001525 logger.Debug("olt-reenabled")
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001526
1527 cloned := proto.Clone(device).(*voltha.Device)
1528 // Update the all ports state on that device to enable
kesavand39e0aa32020-01-28 20:58:50 -05001529
kdarapu1afeceb2020-02-12 01:38:09 -05001530 if err := dh.disableAdminDownPorts(device); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001531 return olterrors.NewErrAdapter("port-status-update-failed-after-olt-reenable", log.Fields{"device": device}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001532 }
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001533 //Update the device oper status as ACTIVE
1534 cloned.OperStatus = voltha.OperStatus_ACTIVE
1535 dh.device = cloned
1536
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001537 if err := dh.coreProxy.DeviceStateUpdate(context.TODO(), cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301538 return olterrors.NewErrAdapter("state-update-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001539 "device-id": device.Id,
1540 "connect-status": cloned.ConnectStatus,
Girish Kumarf26e4882020-03-05 06:49:10 +00001541 "oper-status": cloned.OperStatus}, err)
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001542 }
kesavand39e0aa32020-01-28 20:58:50 -05001543
Shrey Baid807a2a02020-04-09 12:52:45 +05301544 logger.Debugw("reenabledevice-end", log.Fields{"device-id": device.Id})
Girish Gowdru5ba46c92019-04-25 05:00:05 -04001545
1546 return nil
1547}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001548
npujarec5762e2020-01-01 14:08:48 +05301549func (dh *DeviceHandler) clearUNIData(ctx context.Context, onu *rsrcMgr.OnuGemInfo) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001550 var uniID uint32
1551 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301552 for _, port := range onu.UniPorts {
1553 uniID = UniIDFromPortNum(uint32(port))
Matteo Scandolo92186242020-06-12 10:54:18 -07001554 logger.Debugw("clearing-resource-data-for-uni-port", log.Fields{"port": port, "uni-id": uniID})
A R Karthick1f85b802019-10-11 05:06:05 +00001555 /* Delete tech-profile instance from the KV store */
npujarec5762e2020-01-01 14:08:48 +05301556 if err = dh.flowMgr.DeleteTechProfileInstances(ctx, onu.IntfID, onu.OnuID, uniID, onu.SerialNumber); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301557 logger.Debugw("failed-to-remove-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
Devmalya Paul495b94a2019-08-27 19:42:00 -04001558 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301559 logger.Debugw("deleted-tech-profile-instance-for-onu", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301560 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
A R Karthick1f85b802019-10-11 05:06:05 +00001561 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301562 dh.resourceMgr.FreeFlowID(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
A R Karthick1f85b802019-10-11 05:06:05 +00001563 }
npujarec5762e2020-01-01 14:08:48 +05301564 tpIDList := dh.resourceMgr.GetTechProfileIDForOnu(ctx, onu.IntfID, onu.OnuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00001565 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301566 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "upstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301567 logger.Debugw("failed-to-remove-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001568 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301569 logger.Debugw("removed-meter-id-for-onu-upstream", log.Fields{"onu-id": onu.OnuID})
npujarec5762e2020-01-01 14:08:48 +05301570 if err = dh.resourceMgr.RemoveMeterIDForOnu(ctx, "downstream", onu.IntfID, onu.OnuID, uniID, tpID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301571 logger.Debugw("failed-to-remove-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Gamze Abakafee36392019-10-03 11:17:24 +00001572 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301573 logger.Debugw("removed-meter-id-for-onu-downstream", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301574 }
npujarec5762e2020-01-01 14:08:48 +05301575 dh.resourceMgr.FreePONResourcesForONU(ctx, onu.IntfID, onu.OnuID, uniID)
1576 if err = dh.resourceMgr.RemoveTechProfileIDsForOnu(ctx, onu.IntfID, onu.OnuID, uniID); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301577 logger.Debugw("failed-to-remove-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301578 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301579 logger.Debugw("removed-tech-profile-id-for-onu", log.Fields{"onu-id": onu.OnuID})
Esin Karaman04166c82020-07-16 14:23:33 +00001580 if err = dh.resourceMgr.DelGemPortPktInOfAllServices(ctx, onu.IntfID, onu.OnuID, uint32(port)); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301581 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 +00001582 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001583 }
1584 return nil
1585}
1586
npujarec5762e2020-01-01 14:08:48 +05301587func (dh *DeviceHandler) clearNNIData(ctx context.Context) error {
Devmalya Paul495b94a2019-08-27 19:42:00 -04001588 nniUniID := -1
1589 nniOnuID := -1
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301590
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001591 if dh.resourceMgr == nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301592 return olterrors.NewErrNotFound("resource-manager", log.Fields{"device-id": dh.device.Id}, nil)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001593 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001594 //Free the flow-ids for the NNI port
npujarec5762e2020-01-01 14:08:48 +05301595 nni, err := dh.resourceMgr.GetNNIFromKVStore(ctx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301596 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001597 return olterrors.NewErrPersistence("get", "nni", 0, nil, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001598 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301599 logger.Debugw("nni-", log.Fields{"nni": nni})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301600 for _, nniIntfID := range nni {
npujarec5762e2020-01-01 14:08:48 +05301601 flowIDs := dh.resourceMgr.GetCurrentFlowIDsForOnu(ctx, uint32(nniIntfID), int32(nniOnuID), int32(nniUniID))
Shrey Baid807a2a02020-04-09 12:52:45 +05301602 logger.Debugw("current-flow-ids-for-nni", log.Fields{"flow-ids": flowIDs})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301603 for _, flowID := range flowIDs {
npujarec5762e2020-01-01 14:08:48 +05301604 dh.resourceMgr.FreeFlowID(ctx, uint32(nniIntfID), -1, -1, uint32(flowID))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301605 }
npujarec5762e2020-01-01 14:08:48 +05301606 dh.resourceMgr.RemoveResourceMap(ctx, nniIntfID, int32(nniOnuID), int32(nniUniID))
Devmalya Paul495b94a2019-08-27 19:42:00 -04001607 }
npujarec5762e2020-01-01 14:08:48 +05301608 if err = dh.resourceMgr.DelNNiFromKVStore(ctx); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001609 return olterrors.NewErrPersistence("clear", "nni", 0, nil, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301610 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001611 return nil
Devmalya Paul495b94a2019-08-27 19:42:00 -04001612}
1613
1614// 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 +05301615func (dh *DeviceHandler) DeleteDevice(ctx context.Context, device *voltha.Device) error {
Shrey Baid807a2a02020-04-09 12:52:45 +05301616 logger.Debug("function-entry-delete-device")
Devmalya Paul495b94a2019-08-27 19:42:00 -04001617 /* Clear the KV store data associated with the all the UNI ports
1618 This clears up flow data and also resource map data for various
1619 other pon resources like alloc_id and gemport_id
1620 */
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001621 go dh.cleanupDeviceResources(ctx)
Shrey Baid807a2a02020-04-09 12:52:45 +05301622 logger.Debug("removed-device-from-Resource-manager-KV-store")
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001623 // Stop the Stats collector
1624 dh.stopCollector <- true
1625 // stop the heartbeat check routine
1626 dh.stopHeartbeatCheck <- true
1627 //Reset the state
1628 if dh.Client != nil {
1629 if _, err := dh.Client.Reboot(ctx, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301630 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001631 }
1632 }
1633 cloned := proto.Clone(device).(*voltha.Device)
1634 cloned.OperStatus = voltha.OperStatus_UNKNOWN
1635 cloned.ConnectStatus = voltha.ConnectStatus_UNREACHABLE
1636 if err := dh.coreProxy.DeviceStateUpdate(ctx, cloned.Id, cloned.ConnectStatus, cloned.OperStatus); err != nil {
1637 return olterrors.NewErrAdapter("device-state-update-failed", log.Fields{
1638 "device-id": device.Id,
1639 "connect-status": cloned.ConnectStatus,
1640 "oper-status": cloned.OperStatus}, err).Log()
1641 }
1642 return nil
1643}
1644func (dh *DeviceHandler) cleanupDeviceResources(ctx context.Context) error {
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001645 if dh.resourceMgr != nil {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301646 noOfPonPorts := dh.resourceMgr.DevInfo.GetPonPorts()
1647 var ponPort uint32
1648 for ponPort = 0; ponPort < noOfPonPorts; ponPort++ {
1649 var onuGemData []rsrcMgr.OnuGemInfo
npujarec5762e2020-01-01 14:08:48 +05301650 err := dh.resourceMgr.ResourceMgrs[ponPort].GetOnuGemInfo(ctx, ponPort, &onuGemData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301651 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301652 return olterrors.NewErrNotFound("onu", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001653 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001654 "pon-port": ponPort}, err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301655 }
1656 for _, onu := range onuGemData {
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301657 onuID := make([]uint32, 1)
Shrey Baid807a2a02020-04-09 12:52:45 +05301658 logger.Debugw("onu-data", log.Fields{"onu": onu})
npujarec5762e2020-01-01 14:08:48 +05301659 if err = dh.clearUNIData(ctx, &onu); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301660 logger.Errorw("failed-to-clear-data-for-onu", log.Fields{"onu-device": onu})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301661 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301662 // Clear flowids for gem cache.
1663 for _, gem := range onu.GemPorts {
npujarec5762e2020-01-01 14:08:48 +05301664 dh.resourceMgr.DeleteFlowIDsForGem(ctx, ponPort, gem)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301665 }
1666 onuID[0] = onu.OnuID
npujarec5762e2020-01-01 14:08:48 +05301667 dh.resourceMgr.FreeonuID(ctx, ponPort, onuID)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301668 }
npujarec5762e2020-01-01 14:08:48 +05301669 dh.resourceMgr.DeleteIntfIDGempMapPath(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301670 onuGemData = nil
npujarec5762e2020-01-01 14:08:48 +05301671 err = dh.resourceMgr.DelOnuGemInfoForIntf(ctx, ponPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301672 if err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05301673 logger.Errorw("failed-to-update-onugem-info", log.Fields{"intfid": ponPort, "onugeminfo": onuGemData})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001674 }
Devmalya Paul495b94a2019-08-27 19:42:00 -04001675 }
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001676 /* Clear the flows from KV store associated with NNI port.
1677 There are mostly trap rules from NNI port (like LLDP)
1678 */
npujarec5762e2020-01-01 14:08:48 +05301679 if err := dh.clearNNIData(ctx); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301680 logger.Errorw("failed-to-clear-data-for-NNI-port", log.Fields{"device-id": dh.device.Id})
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001681 }
A R Karthick1f85b802019-10-11 05:06:05 +00001682
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001683 /* Clear the resource pool for each PON port in the background */
npujarec5762e2020-01-01 14:08:48 +05301684 go dh.resourceMgr.Delete(ctx)
Serkant Uluderya89ff40c2019-10-17 16:02:25 -07001685 }
A R Karthick1f85b802019-10-11 05:06:05 +00001686
Devmalya Paul495b94a2019-08-27 19:42:00 -04001687 /*Delete ONU map for the device*/
Naga Manjunatha8dc9372019-10-31 23:01:18 +05301688 dh.onus.Range(func(key interface{}, value interface{}) bool {
1689 dh.onus.Delete(key)
1690 return true
1691 })
1692
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001693 /*Delete discovered ONU map for the device*/
1694 dh.discOnus.Range(func(key interface{}, value interface{}) bool {
1695 dh.discOnus.Delete(key)
1696 return true
1697 })
1698
Devmalya Paul495b94a2019-08-27 19:42:00 -04001699 return nil
1700}
1701
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001702//RebootDevice reboots the given device
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001703func (dh *DeviceHandler) RebootDevice(device *voltha.Device) error {
1704 if _, err := dh.Client.Reboot(context.Background(), new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301705 return olterrors.NewErrAdapter("olt-reboot-failed", log.Fields{"device-id": dh.device.Id}, err)
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001706 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301707 logger.Debugw("rebooted-device-successfully", log.Fields{"device-id": device.Id})
Girish Gowdru0fe5f7e2019-05-28 05:12:27 -04001708 return nil
1709}
1710
David K. Bainbridge794735f2020-02-11 21:01:37 -08001711func (dh *DeviceHandler) handlePacketIndication(ctx context.Context, packetIn *oop.PacketIndication) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001712 if logger.V(log.DebugLevel) {
1713 logger.Debugw("received-packet-in", log.Fields{
1714 "packet-indication": *packetIn,
1715 "device-id": dh.device.Id,
1716 "packet": hex.EncodeToString(packetIn.Pkt),
1717 })
1718 }
npujarec5762e2020-01-01 14:08:48 +05301719 logicalPortNum, err := dh.flowMgr.GetLogicalPortFromPacketIn(ctx, packetIn)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001720 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00001721 return olterrors.NewErrNotFound("logical-port", log.Fields{"packet": hex.EncodeToString(packetIn.Pkt)}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001722 }
Matteo Scandolo92186242020-06-12 10:54:18 -07001723 if logger.V(log.DebugLevel) {
1724 logger.Debugw("sending-packet-in-to-core", log.Fields{
1725 "logical-port-num": logicalPortNum,
1726 "device-id": dh.device.Id,
1727 "packet": hex.EncodeToString(packetIn.Pkt),
1728 })
1729 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001730 if err := dh.coreProxy.SendPacketIn(context.TODO(), dh.device.Id, logicalPortNum, packetIn.Pkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301731 return olterrors.NewErrCommunication("send-packet-in", log.Fields{
Matteo Scandoloa4e46912020-08-05 15:23:45 -07001732 "destination": "core",
1733 "logical-port-num": logicalPortNum,
1734 "source": dh.device.Type,
1735 "device-id": dh.device.Id,
1736 "packet": hex.EncodeToString(packetIn.Pkt),
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001737 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001738 }
Matteo Scandoloa4e46912020-08-05 15:23:45 -07001739 if logger.V(log.InfoLevel) {
1740 logger.Infow("success-sending-packet-in-to-core!", log.Fields{
1741 "logical-port-num": logicalPortNum,
1742 "packet": hex.EncodeToString(packetIn.Pkt),
1743 "device-id": dh.device.Id,
Matteo Scandolo92186242020-06-12 10:54:18 -07001744 })
1745 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001746 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001747}
1748
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001749// PacketOut sends packet-out from VOLTHA to OLT on the egress port provided
npujarec5762e2020-01-01 14:08:48 +05301750func (dh *DeviceHandler) PacketOut(ctx context.Context, egressPortNo int, packet *of.OfpPacketOut) error {
Matteo Scandolo92186242020-06-12 10:54:18 -07001751 if logger.V(log.DebugLevel) {
1752 logger.Debugw("incoming-packet-out", log.Fields{
1753 "device-id": dh.device.Id,
1754 "egress-port-no": egressPortNo,
1755 "pkt-length": len(packet.Data),
1756 "packet": hex.EncodeToString(packet.Data),
1757 })
1758 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001759
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001760 egressPortType := IntfIDToPortTypeName(uint32(egressPortNo))
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001761 if egressPortType == voltha.Port_ETHERNET_UNI {
Matt Jeanneret1359c732019-08-01 21:40:02 -04001762 outerEthType := (uint16(packet.Data[12]) << 8) | uint16(packet.Data[13])
1763 innerEthType := (uint16(packet.Data[16]) << 8) | uint16(packet.Data[17])
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301764 if outerEthType == 0x8942 || outerEthType == 0x88cc {
1765 // Do not packet-out lldp packets on uni port.
1766 // ONOS has no clue about uni/nni ports, it just packets out on all
1767 // available ports on the Logical Switch. It should not be interested
1768 // in the UNI links.
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001769 logger.Debugw("dropping-lldp-packet-out-on-uni", log.Fields{
1770 "device-id": dh.device.Id,
1771 })
Girish Gowdra6e1534a2019-11-15 19:24:04 +05301772 return nil
1773 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001774 if outerEthType == 0x88a8 || outerEthType == 0x8100 {
1775 if innerEthType == 0x8100 {
1776 // q-in-q 802.1ad or 802.1q double tagged packet.
1777 // slice out the outer tag.
1778 packet.Data = append(packet.Data[:12], packet.Data[16:]...)
Matteo Scandolo92186242020-06-12 10:54:18 -07001779 if logger.V(log.DebugLevel) {
1780 logger.Debugw("packet-now-single-tagged", log.Fields{
1781 "packet-data": hex.EncodeToString(packet.Data),
1782 "device-id": dh.device.Id,
1783 })
1784 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001785 }
1786 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001787 intfID := IntfIDFromUniPortNum(uint32(egressPortNo))
1788 onuID := OnuIDFromPortNum(uint32(egressPortNo))
Manikkaraj kb1d51442019-07-23 10:41:02 -04001789 uniID := UniIDFromPortNum(uint32(egressPortNo))
1790
Esin Karaman04166c82020-07-16 14:23:33 +00001791 gemPortID, err := dh.flowMgr.GetPacketOutGemPortID(ctx, intfID, onuID, uint32(egressPortNo), packet.Data)
Manikkaraj kb1d51442019-07-23 10:41:02 -04001792 if err != nil {
1793 // In this case the openolt agent will receive the gemPortID as 0.
1794 // The agent tries to retrieve the gemPortID in this case.
1795 // This may not always succeed at the agent and packetOut may fail.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001796 logger.Errorw("failed-to-retrieve-gemport-id-for-packet-out", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001797 "intf-id": intfID,
1798 "onu-id": onuID,
1799 "uni-id": uniID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001800 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301801 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001802 })
Manikkaraj kb1d51442019-07-23 10:41:02 -04001803 }
1804
1805 onuPkt := oop.OnuPacket{IntfId: intfID, OnuId: onuID, PortNo: uint32(egressPortNo), GemportId: gemPortID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001806
Matteo Scandolo92186242020-06-12 10:54:18 -07001807 if logger.V(log.DebugLevel) {
1808 logger.Debugw("sending-packet-to-onu", log.Fields{
1809 "egress-port-no": egressPortNo,
1810 "intf-id": intfID,
1811 "onu-id": onuID,
1812 "uni-id": uniID,
1813 "gem-port-id": gemPortID,
1814 "packet": hex.EncodeToString(packet.Data),
1815 "device-id": dh.device.Id,
1816 })
1817 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001818
npujarec5762e2020-01-01 14:08:48 +05301819 if _, err := dh.Client.OnuPacketOut(ctx, &onuPkt); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301820 return olterrors.NewErrCommunication("packet-out-send", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001821 "source": "adapter",
1822 "destination": "onu",
1823 "egress-port-number": egressPortNo,
Matteo Scandolo92186242020-06-12 10:54:18 -07001824 "intf-id": intfID,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001825 "oni-id": onuID,
1826 "uni-id": uniID,
1827 "gem-port-id": gemPortID,
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001828 "packet": hex.EncodeToString(packet.Data),
1829 "device-id": dh.device.Id,
1830 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001831 }
1832 } else if egressPortType == voltha.Port_ETHERNET_NNI {
David K. Bainbridge794735f2020-02-11 21:01:37 -08001833 nniIntfID, err := IntfIDFromNniPortNum(uint32(egressPortNo))
1834 if err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001835 return olterrors.NewErrInvalidValue(log.Fields{
1836 "egress-nni-port": egressPortNo,
1837 "device-id": dh.device.Id,
1838 }, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001839 }
1840 uplinkPkt := oop.UplinkPacket{IntfId: nniIntfID, Pkt: packet.Data}
Matt Jeanneret1359c732019-08-01 21:40:02 -04001841
Matteo Scandolo92186242020-06-12 10:54:18 -07001842 if logger.V(log.DebugLevel) {
1843 logger.Debugw("sending-packet-to-nni", log.Fields{
1844 "uplink-pkt": uplinkPkt,
1845 "packet": hex.EncodeToString(packet.Data),
1846 "device-id": dh.device.Id,
1847 })
1848 }
Matt Jeanneret1359c732019-08-01 21:40:02 -04001849
npujarec5762e2020-01-01 14:08:48 +05301850 if _, err := dh.Client.UplinkPacketOut(ctx, &uplinkPkt); err != nil {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001851 return olterrors.NewErrCommunication("packet-out-to-nni", log.Fields{
1852 "packet": hex.EncodeToString(packet.Data),
1853 "device-id": dh.device.Id,
1854 }, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001855 }
1856 } else {
Shrey Baid807a2a02020-04-09 12:52:45 +05301857 logger.Warnw("packet-out-to-this-interface-type-not-implemented", log.Fields{
1858 "egress-port-no": egressPortNo,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001859 "egressPortType": egressPortType,
1860 "packet": hex.EncodeToString(packet.Data),
Thomas Lee S985938d2020-05-04 11:40:41 +05301861 "device-id": dh.device.Id,
Matteo Scandolo6056e822019-11-13 14:05:29 -08001862 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001863 }
1864 return nil
1865}
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001866
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001867func (dh *DeviceHandler) formOnuKey(intfID, onuID uint32) string {
1868 return "" + strconv.Itoa(int(intfID)) + "." + strconv.Itoa(int(onuID))
Mahir Gunyela3f9add2019-06-06 15:13:19 -07001869}
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301870
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001871func startHeartbeatCheck(ctx context.Context, dh *DeviceHandler) {
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301872 // start the heartbeat check towards the OLT.
1873 var timerCheck *time.Timer
1874
1875 for {
1876 heartbeatTimer := time.NewTimer(dh.openOLT.HeartbeatCheckInterval)
1877 select {
1878 case <-heartbeatTimer.C:
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001879 ctxWithTimeout, cancel := context.WithTimeout(context.Background(), dh.openOLT.GrpcTimeoutInterval)
1880 if heartBeat, err := dh.Client.HeartbeatCheck(ctxWithTimeout, new(oop.Empty)); err != nil {
Thomas Lee S985938d2020-05-04 11:40:41 +05301881 logger.Warnw("hearbeat-failed", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301882 if timerCheck == nil {
1883 // start a after func, when expired will update the state to the core
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001884 timerCheck = time.AfterFunc(dh.openOLT.HeartbeatFailReportInterval, func() { dh.updateStateUnreachable(ctx) })
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301885 }
1886 } else {
1887 if timerCheck != nil {
1888 if timerCheck.Stop() {
Thomas Lee S985938d2020-05-04 11:40:41 +05301889 logger.Debugw("got-hearbeat-within-timeout", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301890 }
1891 timerCheck = nil
1892 }
Shrey Baid807a2a02020-04-09 12:52:45 +05301893 logger.Debugw("hearbeat",
1894 log.Fields{"signature": heartBeat,
Thomas Lee S985938d2020-05-04 11:40:41 +05301895 "device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301896 }
1897 cancel()
1898 case <-dh.stopHeartbeatCheck:
Thomas Lee S985938d2020-05-04 11:40:41 +05301899 logger.Debugw("stopping-heart-beat-check", log.Fields{"device-id": dh.device.Id})
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301900 return
1901 }
1902 }
1903}
1904
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001905func (dh *DeviceHandler) updateStateUnreachable(ctx context.Context) {
1906 device, err := dh.coreProxy.GetDevice(ctx, dh.device.Id, dh.device.Id)
1907 if err != nil || device == nil {
1908 olterrors.NewErrNotFound("device", log.Fields{"device-id": dh.device.Id}, err).Log()
1909 }
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301910
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001911 if device.ConnectStatus == voltha.ConnectStatus_REACHABLE {
1912 if err = dh.coreProxy.DeviceStateUpdate(ctx, dh.device.Id, voltha.ConnectStatus_UNREACHABLE, voltha.OperStatus_UNKNOWN); err != nil {
1913 olterrors.NewErrAdapter("device-state-update-failed", log.Fields{"device-id": dh.device.Id}, err).LogAt(log.ErrorLevel)
1914 }
1915 if err = dh.coreProxy.PortsStateUpdate(ctx, dh.device.Id, voltha.OperStatus_UNKNOWN); err != nil {
1916 olterrors.NewErrAdapter("port-update-failed", log.Fields{"device-id": dh.device.Id}, err).Log()
1917 }
1918 go dh.cleanupDeviceResources(ctx)
1919
Girish Gowdra3ab6d212020-03-24 17:33:15 -07001920 dh.lockDevice.RLock()
1921 // Stop the read indication only if it the routine is active
1922 // The read indication would have already stopped due to failure on the gRPC stream following OLT going unreachable
1923 // Sending message on the 'stopIndication' channel again will cause the readIndication routine to immediately stop
1924 // on next execution of the readIndication routine.
1925 if dh.isReadIndicationRoutineActive {
1926 dh.stopIndications <- true
1927 }
1928 dh.lockDevice.RUnlock()
1929
Chaitrashree G Sa4649252020-03-11 21:24:11 -04001930 dh.transitionMap.Handle(ctx, DeviceInit)
1931
Abhilash Laxmeshwarf9942e92020-01-07 15:32:44 +05301932 }
1933}
kesavand39e0aa32020-01-28 20:58:50 -05001934
1935// EnablePort to enable Pon interface
1936func (dh *DeviceHandler) EnablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001937 logger.Debugw("enable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001938 return dh.modifyPhyPort(port, true)
kesavand39e0aa32020-01-28 20:58:50 -05001939}
1940
1941// DisablePort to disable pon interface
1942func (dh *DeviceHandler) DisablePort(port *voltha.Port) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00001943 logger.Debugw("disable-port", log.Fields{"Device": dh.device, "port": port})
kdarapu1afeceb2020-02-12 01:38:09 -05001944 return dh.modifyPhyPort(port, false)
kesavand39e0aa32020-01-28 20:58:50 -05001945}
1946
kdarapu1afeceb2020-02-12 01:38:09 -05001947//modifyPhyPort is common function to enable and disable the port. parm :enablePort, true to enablePort and false to disablePort.
1948func (dh *DeviceHandler) modifyPhyPort(port *voltha.Port, enablePort bool) error {
npujarec5762e2020-01-01 14:08:48 +05301949 ctx := context.Background()
Thomas Lee S985938d2020-05-04 11:40:41 +05301950 logger.Infow("modifyPhyPort", log.Fields{"port": port, "Enable": enablePort, "device-id": dh.device.Id})
kesavand39e0aa32020-01-28 20:58:50 -05001951 if port.GetType() == voltha.Port_ETHERNET_NNI {
1952 // Bug is opened for VOL-2505 to support NNI disable feature.
Girish Kumar2ad402b2020-03-20 19:45:12 +00001953 logger.Infow("voltha-supports-single-nni-hence-disable-of-nni-not-allowed",
Shrey Baid807a2a02020-04-09 12:52:45 +05301954 log.Fields{"device": dh.device, "port": port})
Thomas Lee S94109f12020-03-03 16:39:29 +05301955 return olterrors.NewErrAdapter("illegal-port-request", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001956 "port-type": port.GetType,
Girish Kumarf26e4882020-03-05 06:49:10 +00001957 "enable-state": enablePort}, nil)
kesavand39e0aa32020-01-28 20:58:50 -05001958 }
1959 // fetch interfaceid from PortNo
1960 ponID := PortNoToIntfID(port.GetPortNo(), voltha.Port_PON_OLT)
1961 ponIntf := &oop.Interface{IntfId: ponID}
1962 var operStatus voltha.OperStatus_Types
1963 if enablePort {
1964 operStatus = voltha.OperStatus_ACTIVE
npujarec5762e2020-01-01 14:08:48 +05301965 out, err := dh.Client.EnablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001966
1967 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301968 return olterrors.NewErrAdapter("pon-port-enable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001969 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001970 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001971 }
1972 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001973 dh.activePorts.Store(ponID, true)
Shrey Baid807a2a02020-04-09 12:52:45 +05301974 logger.Infow("enabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001975 } else {
1976 operStatus = voltha.OperStatus_UNKNOWN
npujarec5762e2020-01-01 14:08:48 +05301977 out, err := dh.Client.DisablePonIf(ctx, ponIntf)
kesavand39e0aa32020-01-28 20:58:50 -05001978 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301979 return olterrors.NewErrAdapter("pon-port-disable-failed", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001980 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001981 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001982 }
1983 // updating interface local cache for collecting stats
Chaitrashree G Sef088112020-02-03 21:39:27 -05001984 dh.activePorts.Store(ponID, false)
Shrey Baid807a2a02020-04-09 12:52:45 +05301985 logger.Infow("disabled-pon-port", log.Fields{"out": out, "device-id": dh.device, "Port": port})
kesavand39e0aa32020-01-28 20:58:50 -05001986 }
Thomas Lee S985938d2020-05-04 11:40:41 +05301987 if err := dh.coreProxy.PortStateUpdate(ctx, dh.device.Id, voltha.Port_PON_OLT, port.PortNo, operStatus); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301988 return olterrors.NewErrAdapter("port-state-update-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05301989 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00001990 "port": port.PortNo}, err)
kesavand39e0aa32020-01-28 20:58:50 -05001991 }
1992 return nil
1993}
1994
kdarapu1afeceb2020-02-12 01:38:09 -05001995//disableAdminDownPorts disables the ports, if the corresponding port Adminstate is disabled on reboot and Renable device.
1996func (dh *DeviceHandler) disableAdminDownPorts(device *voltha.Device) error {
kesavand39e0aa32020-01-28 20:58:50 -05001997 cloned := proto.Clone(device).(*voltha.Device)
1998 // Disable the port and update the oper_port_status to core
1999 // if the Admin state of the port is disabled on reboot and re-enable device.
2000 for _, port := range cloned.Ports {
2001 if port.AdminState == common.AdminState_DISABLED {
kdarapu1afeceb2020-02-12 01:38:09 -05002002 if err := dh.DisablePort(port); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302003 return olterrors.NewErrAdapter("port-disable-failed", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302004 "device-id": dh.device.Id,
Girish Kumarf26e4882020-03-05 06:49:10 +00002005 "port": port}, err)
kesavand39e0aa32020-01-28 20:58:50 -05002006 }
2007 }
2008 }
2009 return nil
2010}
2011
2012//populateActivePorts to populate activePorts map
2013func (dh *DeviceHandler) populateActivePorts(device *voltha.Device) {
Shrey Baid807a2a02020-04-09 12:52:45 +05302014 logger.Infow("populateActiveports", log.Fields{"Device": device})
kesavand39e0aa32020-01-28 20:58:50 -05002015 for _, port := range device.Ports {
2016 if port.Type == voltha.Port_ETHERNET_NNI {
2017 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002018 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), true)
kesavand39e0aa32020-01-28 20:58:50 -05002019 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002020 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_ETHERNET_NNI), false)
kesavand39e0aa32020-01-28 20:58:50 -05002021 }
2022 }
2023 if port.Type == voltha.Port_PON_OLT {
2024 if port.OperStatus == voltha.OperStatus_ACTIVE {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002025 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), true)
kesavand39e0aa32020-01-28 20:58:50 -05002026 } else {
Chaitrashree G Sef088112020-02-03 21:39:27 -05002027 dh.activePorts.Store(PortNoToIntfID(port.PortNo, voltha.Port_PON_OLT), false)
kesavand39e0aa32020-01-28 20:58:50 -05002028 }
2029 }
2030 }
2031}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002032
2033// ChildDeviceLost deletes ONU and clears pon resources related to it.
2034func (dh *DeviceHandler) ChildDeviceLost(ctx context.Context, pPortNo uint32, onuID uint32) error {
Girish Kumar2ad402b2020-03-20 19:45:12 +00002035 logger.Debugw("child-device-lost", log.Fields{"pdeviceID": dh.device.Id})
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002036 intfID := PortNoToIntfID(pPortNo, voltha.Port_PON_OLT)
2037 onuKey := dh.formOnuKey(intfID, onuID)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002038 onuDevice, ok := dh.onus.Load(onuKey)
2039 if !ok {
Thomas Lee S94109f12020-03-03 16:39:29 +05302040 return olterrors.NewErrAdapter("failed-to-load-onu-details",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002041 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002042 "device-id": dh.device.Id,
2043 "onu-id": onuID,
2044 "intf-id": intfID}, nil).Log()
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002045 }
2046 var sn *oop.SerialNumber
2047 var err error
2048 if sn, err = dh.deStringifySerialNumber(onuDevice.(*OnuDevice).serialNumber); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302049 return olterrors.NewErrAdapter("failed-to-destringify-serial-number",
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002050 log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302051 "devicer-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002052 "serial-number": onuDevice.(*OnuDevice).serialNumber}, err).Log()
2053 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002054
2055 for uniID := 0; uniID < MaxUnisPerOnu; uniID++ {
2056 var flowRemoveData pendingFlowRemoveData
2057 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uint32(uniID)}
2058 dh.lockDevice.RLock()
2059 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2060 dh.lockDevice.RUnlock()
2061 continue
2062 }
2063 dh.lockDevice.RUnlock()
2064
2065 log.Debugw("wait-for-flow-remove-complete-before-processing-child-device-lost",
2066 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2067 // Wait for all flow removes to finish first
2068 <-flowRemoveData.allFlowsRemoved
2069 log.Debugw("flow-removes-complete-for-subscriber",
2070 log.Fields{"int-id": intfID, "onu-id": onuID, "uni-id": uniID})
2071 }
2072
2073 onu := &oop.Onu{IntfId: intfID, OnuId: onuID, SerialNumber: sn}
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002074 if _, err := dh.Client.DeleteOnu(context.Background(), onu); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302075 return olterrors.NewErrAdapter("failed-to-delete-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302076 "device-id": dh.device.Id,
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002077 "onu-id": onuID}, err).Log()
2078 }
2079 //clear PON resources associated with ONU
2080 var onuGemData []rsrcMgr.OnuGemInfo
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002081 if onuMgr, ok := dh.resourceMgr.ResourceMgrs[intfID]; !ok {
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002082 logger.Warnw("failed-to-get-resource-manager-for-interface-Id", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002083 "device-id": dh.device.Id,
2084 "intf-id": intfID})
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002085 } else {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002086 if err := onuMgr.GetOnuGemInfo(ctx, intfID, &onuGemData); err != nil {
Shrey Baid807a2a02020-04-09 12:52:45 +05302087 logger.Warnw("failed-to-get-onu-info-for-pon-port", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002088 "device-id": dh.device.Id,
2089 "intf-id": intfID,
2090 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002091 } else {
2092 for i, onu := range onuGemData {
2093 if onu.OnuID == onuID && onu.SerialNumber == onuDevice.(*OnuDevice).serialNumber {
Shrey Baid807a2a02020-04-09 12:52:45 +05302094 logger.Debugw("onu-data", log.Fields{"onu": onu})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002095 if err := dh.clearUNIData(ctx, &onu); err != nil {
2096 logger.Warnw("failed-to-clear-uni-data-for-onu", log.Fields{
Thomas Lee S985938d2020-05-04 11:40:41 +05302097 "device-id": dh.device.Id,
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002098 "onu-device": onu,
2099 "error": err})
2100 }
2101 // Clear flowids for gem cache.
2102 for _, gem := range onu.GemPorts {
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002103 dh.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gem)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002104 }
2105 onuGemData = append(onuGemData[:i], onuGemData[i+1:]...)
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002106 err := onuMgr.AddOnuGemInfo(ctx, intfID, onuGemData)
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002107 if err != nil {
2108 logger.Warnw("persistence-update-onu-gem-info-failed", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002109 "intf-id": intfID,
2110 "onu-device": onu,
2111 "onu-gem": onuGemData,
2112 "error": err})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002113 //Not returning error on cleanup.
2114 }
Girish Gowdra89ae6d82020-05-28 23:40:53 -07002115 logger.Debugw("removed-onu-gem-info", log.Fields{"intf": intfID, "onu-device": onu, "onugem": onuGemData})
2116 dh.resourceMgr.FreeonuID(ctx, intfID, []uint32{onu.OnuID})
Andrea Campanella668ea5f2020-03-31 13:51:06 +02002117 break
Chaitrashree G Se420b5f2020-02-23 21:34:54 -05002118 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002119 }
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002120 }
2121 }
2122 dh.onus.Delete(onuKey)
2123 dh.discOnus.Delete(onuDevice.(*OnuDevice).serialNumber)
2124 return nil
2125}
Girish Gowdracefae192020-03-19 18:14:10 -07002126
2127func getInPortFromFlow(flow *of.OfpFlowStats) uint32 {
2128 for _, field := range flows.GetOfbFields(flow) {
2129 if field.Type == flows.IN_PORT {
2130 return field.GetPort()
2131 }
2132 }
2133 return InvalidPort
2134}
2135
2136func getOutPortFromFlow(flow *of.OfpFlowStats) uint32 {
2137 for _, action := range flows.GetActions(flow) {
2138 if action.Type == flows.OUTPUT {
2139 if out := action.GetOutput(); out != nil {
2140 return out.GetPort()
2141 }
2142 }
2143 }
2144 return InvalidPort
2145}
2146
2147func (dh *DeviceHandler) incrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2148 inPort, outPort := getPorts(flow)
Matteo Scandolo92186242020-06-12 10:54:18 -07002149 logger.Debugw("increment-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002150 if inPort != InvalidPort && outPort != InvalidPort {
2151 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2152 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Matteo Scandolo92186242020-06-12 10:54:18 -07002153 logger.Debugw("increment-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002154
2155 dh.lockDevice.Lock()
2156 defer dh.lockDevice.Unlock()
2157 flowRemoveData, ok := dh.pendingFlowRemoveDataPerSubscriber[key]
2158 if !ok {
2159 flowRemoveData = pendingFlowRemoveData{
2160 pendingFlowRemoveCount: 0,
2161 allFlowsRemoved: make(chan struct{}),
2162 }
2163 }
2164 flowRemoveData.pendingFlowRemoveCount++
2165 dh.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
2166
Shrey Baid807a2a02020-04-09 12:52:45 +05302167 logger.Debugw("current-flow-remove-count–increment",
Matteo Scandolo92186242020-06-12 10:54:18 -07002168 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
Girish Gowdracefae192020-03-19 18:14:10 -07002169 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2170 }
2171}
2172
2173func (dh *DeviceHandler) decrementActiveFlowRemoveCount(flow *of.OfpFlowStats) {
2174 inPort, outPort := getPorts(flow)
Matteo Scandolo92186242020-06-12 10:54:18 -07002175 logger.Debugw("decrement-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002176 if inPort != InvalidPort && outPort != InvalidPort {
2177 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
2178 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Matteo Scandolo92186242020-06-12 10:54:18 -07002179 logger.Debugw("decrement-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002180
2181 dh.lockDevice.Lock()
2182 defer dh.lockDevice.Unlock()
2183 if val, ok := dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07002184 logger.Fatalf("flow-remove-key-not-found", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002185 } else {
2186 if val.pendingFlowRemoveCount > 0 {
2187 val.pendingFlowRemoveCount--
2188 }
Shrey Baid807a2a02020-04-09 12:52:45 +05302189 logger.Debugw("current-flow-remove-count-after-decrement",
Matteo Scandolo92186242020-06-12 10:54:18 -07002190 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
Girish Gowdracefae192020-03-19 18:14:10 -07002191 "currCnt": dh.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
2192 // If all flow removes have finished, then close the channel to signal the receiver
2193 // to go ahead with flow adds.
2194 if val.pendingFlowRemoveCount == 0 {
2195 close(val.allFlowsRemoved)
2196 delete(dh.pendingFlowRemoveDataPerSubscriber, key)
2197 return
2198 }
2199 dh.pendingFlowRemoveDataPerSubscriber[key] = val
2200 }
2201 }
2202}
2203
2204func (dh *DeviceHandler) waitForFlowRemoveToFinish(flow *of.OfpFlowStats) {
2205 var flowRemoveData pendingFlowRemoveData
2206 var ok bool
2207 inPort, outPort := getPorts(flow)
Matteo Scandolo92186242020-06-12 10:54:18 -07002208 logger.Debugw("wait-for-flow-remove-to-finish-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
Girish Gowdracefae192020-03-19 18:14:10 -07002209 if inPort != InvalidPort && outPort != InvalidPort {
2210 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
2211 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
Matteo Scandolo92186242020-06-12 10:54:18 -07002212 logger.Debugw("wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002213
2214 dh.lockDevice.RLock()
2215 if flowRemoveData, ok = dh.pendingFlowRemoveDataPerSubscriber[key]; !ok {
Matteo Scandolo92186242020-06-12 10:54:18 -07002216 logger.Debugw("no-pending-flow-to-remove", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002217 dh.lockDevice.RUnlock()
2218 return
2219 }
2220 dh.lockDevice.RUnlock()
2221
2222 // Wait for all flow removes to finish first
2223 <-flowRemoveData.allFlowsRemoved
2224
Matteo Scandolo92186242020-06-12 10:54:18 -07002225 logger.Debugw("all-flows-cleared--handling-flow-add-now", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdracefae192020-03-19 18:14:10 -07002226 }
2227}
2228
2229func getPorts(flow *of.OfpFlowStats) (uint32, uint32) {
2230 inPort := getInPortFromFlow(flow)
2231 outPort := getOutPortFromFlow(flow)
2232
2233 if inPort == InvalidPort || outPort == InvalidPort {
2234 return inPort, outPort
2235 }
2236
2237 if isControllerFlow := IsControllerBoundFlow(outPort); isControllerFlow {
2238 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
2239 if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2240 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2241 return uniPort, outPort
2242 }
2243 }
2244 } else {
2245 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
2246 if portType := IntfIDToPortTypeName(outPort); portType == voltha.Port_PON_OLT {
2247 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2248 return inPort, uniPort
2249 }
2250 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
2251 } else if portType := IntfIDToPortTypeName(inPort); portType == voltha.Port_PON_OLT {
2252 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
2253 return uniPort, outPort
2254 }
2255 }
2256 }
2257
2258 return InvalidPort, InvalidPort
2259}
Matt Jeanneretceea2e02020-03-27 14:19:57 -04002260
2261func extractOmciTransactionID(omciPkt []byte) uint16 {
2262 if len(omciPkt) > 3 {
2263 d := omciPkt[0:2]
2264 transid := binary.BigEndian.Uint16(d)
2265 return transid
2266 }
2267 return 0
2268}
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002269
2270// StoreOnuDevice stores the onu parameters to the local cache.
2271func (dh *DeviceHandler) StoreOnuDevice(onuDevice *OnuDevice) {
2272 onuKey := dh.formOnuKey(onuDevice.intfID, onuDevice.onuID)
2273 dh.onus.Store(onuKey, onuDevice)
2274}
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002275
Devmalya Paula1efa642020-04-20 01:36:43 -04002276// setOnuITUPonAlarmConfig sets the parameters in the openolt agent for raising the ONU ITU PON alarms.
2277func (dh *DeviceHandler) setOnuITUPonAlarmConfig(config *oop.OnuItuPonAlarm) error {
2278 if _, err := dh.Client.OnuItuPonAlarmSet(context.Background(), config); err != nil {
2279 return err
2280 }
2281 logger.Debugw("onu-itu-pon-alarm-config-set-successful", log.Fields{"config": config})
2282 return nil
2283}
2284
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002285func (dh *DeviceHandler) getExtValue(device *voltha.Device, value voltha.ValueType_Type) (*voltha.ReturnValues, error) {
2286 var err error
Andrea Campanella9931ad62020-04-28 15:11:06 +02002287 var sn *oop.SerialNumber
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002288 var ID uint32
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002289 resp := new(voltha.ReturnValues)
2290 valueparam := new(oop.ValueParam)
2291 ctx := context.Background()
2292 log.Infow("getExtValue", log.Fields{"onu-id": device.Id, "pon-intf": device.ParentPortNo})
Dinesh Belwalkardb587af2020-02-27 15:37:16 -08002293 if sn, err = dh.deStringifySerialNumber(device.SerialNumber); err != nil {
2294 return nil, err
2295 }
2296 ID = device.ProxyAddress.GetOnuId()
2297 Onu := oop.Onu{IntfId: device.ParentPortNo, OnuId: ID, SerialNumber: sn}
2298 valueparam.Onu = &Onu
2299 valueparam.Value = value
2300
2301 // This API is unsupported until agent patch is added
2302 resp.Unsupported = uint32(value)
2303 _ = ctx
2304
2305 // Uncomment this code once agent changes are complete and tests
2306 /*
2307 resp, err = dh.Client.GetValue(ctx, valueparam)
2308 if err != nil {
2309 log.Errorw("error-while-getValue", log.Fields{"DeviceID": dh.device, "onu-id": onuid, "error": err})
2310 return nil, err
2311 }
2312 */
2313
2314 log.Infow("get-ext-value", log.Fields{"resp": resp, "device-id": dh.device, "onu-id": device.Id, "pon-intf": device.ParentPortNo})
2315 return resp, nil
2316}